hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
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,14 +1047,8 @@
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
1050
+ audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
1051
+ AUDIT_XT_OP_REPLACE, GFP_KERNEL);
10611052 return ret;
10621053
10631054 free_unlock:
....@@ -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);
....@@ -2173,7 +2097,7 @@
21732097
21742098
21752099 static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
2176
- void __user *user, unsigned int len)
2100
+ sockptr_t arg, unsigned int len)
21772101 {
21782102 struct compat_ebt_replace tmp;
21792103 int i;
....@@ -2181,7 +2105,7 @@
21812105 if (len < sizeof(tmp))
21822106 return -EINVAL;
21832107
2184
- if (copy_from_user(&tmp, user, sizeof(tmp)))
2108
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)))
21852109 return -EFAULT;
21862110
21872111 if (len != sizeof(tmp) + tmp.entries_size)
....@@ -2208,8 +2132,7 @@
22082132 return 0;
22092133 }
22102134
2211
-static int compat_do_replace(struct net *net, void __user *user,
2212
- unsigned int len)
2135
+static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
22132136 {
22142137 int ret, i, countersize, size64;
22152138 struct ebt_table_info *newinfo;
....@@ -2217,10 +2140,10 @@
22172140 struct ebt_entries_buf_state state;
22182141 void *entries_tmp;
22192142
2220
- ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
2143
+ ret = compat_copy_ebt_replace_from_user(&tmp, arg, len);
22212144 if (ret) {
22222145 /* try real handler in case userland supplied needed padding */
2223
- if (ret == -EINVAL && do_replace(net, user, len) == 0)
2146
+ if (ret == -EINVAL && do_replace(net, arg, len) == 0)
22242147 ret = 0;
22252148 return ret;
22262149 }
....@@ -2311,42 +2234,20 @@
23112234 goto free_entries;
23122235 }
23132236
2314
-static int compat_update_counters(struct net *net, void __user *user,
2237
+static int compat_update_counters(struct net *net, sockptr_t arg,
23152238 unsigned int len)
23162239 {
23172240 struct compat_ebt_replace hlp;
23182241
2319
- if (copy_from_user(&hlp, user, sizeof(hlp)))
2242
+ if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
23202243 return -EFAULT;
23212244
23222245 /* try real handler in case userland supplied needed padding */
23232246 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
2324
- return update_counters(net, user, len);
2247
+ return update_counters(net, arg, len);
23252248
23262249 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;
2250
+ hlp.num_counters, len);
23502251 }
23512252
23522253 static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
....@@ -2357,13 +2258,9 @@
23572258 struct ebt_table *t;
23582259 struct net *net = sock_net(sk);
23592260
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);
2261
+ if ((cmd == EBT_SO_GET_INFO || cmd == EBT_SO_GET_INIT_INFO) &&
2262
+ *len != sizeof(struct compat_ebt_replace))
2263
+ return -EINVAL;
23672264
23682265 if (copy_from_user(&tmp, user, sizeof(tmp)))
23692266 return -EFAULT;
....@@ -2426,20 +2323,112 @@
24262323 }
24272324 #endif
24282325
2326
+static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2327
+{
2328
+ struct net *net = sock_net(sk);
2329
+ struct ebt_replace tmp;
2330
+ struct ebt_table *t;
2331
+ int ret;
2332
+
2333
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2334
+ return -EPERM;
2335
+
2336
+#ifdef CONFIG_COMPAT
2337
+ /* try real handler in case userland supplied needed padding */
2338
+ if (in_compat_syscall() &&
2339
+ ((cmd != EBT_SO_GET_INFO && cmd != EBT_SO_GET_INIT_INFO) ||
2340
+ *len != sizeof(tmp)))
2341
+ return compat_do_ebt_get_ctl(sk, cmd, user, len);
2342
+#endif
2343
+
2344
+ if (copy_from_user(&tmp, user, sizeof(tmp)))
2345
+ return -EFAULT;
2346
+
2347
+ tmp.name[sizeof(tmp.name) - 1] = '\0';
2348
+
2349
+ t = find_table_lock(net, tmp.name, &ret, &ebt_mutex);
2350
+ if (!t)
2351
+ return ret;
2352
+
2353
+ switch (cmd) {
2354
+ case EBT_SO_GET_INFO:
2355
+ case EBT_SO_GET_INIT_INFO:
2356
+ if (*len != sizeof(struct ebt_replace)) {
2357
+ ret = -EINVAL;
2358
+ mutex_unlock(&ebt_mutex);
2359
+ break;
2360
+ }
2361
+ if (cmd == EBT_SO_GET_INFO) {
2362
+ tmp.nentries = t->private->nentries;
2363
+ tmp.entries_size = t->private->entries_size;
2364
+ tmp.valid_hooks = t->valid_hooks;
2365
+ } else {
2366
+ tmp.nentries = t->table->nentries;
2367
+ tmp.entries_size = t->table->entries_size;
2368
+ tmp.valid_hooks = t->table->valid_hooks;
2369
+ }
2370
+ mutex_unlock(&ebt_mutex);
2371
+ if (copy_to_user(user, &tmp, *len) != 0) {
2372
+ ret = -EFAULT;
2373
+ break;
2374
+ }
2375
+ ret = 0;
2376
+ break;
2377
+
2378
+ case EBT_SO_GET_ENTRIES:
2379
+ case EBT_SO_GET_INIT_ENTRIES:
2380
+ ret = copy_everything_to_user(t, user, len, cmd);
2381
+ mutex_unlock(&ebt_mutex);
2382
+ break;
2383
+
2384
+ default:
2385
+ mutex_unlock(&ebt_mutex);
2386
+ ret = -EINVAL;
2387
+ }
2388
+
2389
+ return ret;
2390
+}
2391
+
2392
+static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
2393
+ unsigned int len)
2394
+{
2395
+ struct net *net = sock_net(sk);
2396
+ int ret;
2397
+
2398
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2399
+ return -EPERM;
2400
+
2401
+ switch (cmd) {
2402
+ case EBT_SO_SET_ENTRIES:
2403
+#ifdef CONFIG_COMPAT
2404
+ if (in_compat_syscall())
2405
+ ret = compat_do_replace(net, arg, len);
2406
+ else
2407
+#endif
2408
+ ret = do_replace(net, arg, len);
2409
+ break;
2410
+ case EBT_SO_SET_COUNTERS:
2411
+#ifdef CONFIG_COMPAT
2412
+ if (in_compat_syscall())
2413
+ ret = compat_update_counters(net, arg, len);
2414
+ else
2415
+#endif
2416
+ ret = update_counters(net, arg, len);
2417
+ break;
2418
+ default:
2419
+ ret = -EINVAL;
2420
+ }
2421
+ return ret;
2422
+}
2423
+
24292424 static struct nf_sockopt_ops ebt_sockopts = {
24302425 .pf = PF_INET,
24312426 .set_optmin = EBT_BASE_CTL,
24322427 .set_optmax = EBT_SO_SET_MAX + 1,
24332428 .set = do_ebt_set_ctl,
2434
-#ifdef CONFIG_COMPAT
2435
- .compat_set = compat_do_ebt_set_ctl,
2436
-#endif
24372429 .get_optmin = EBT_BASE_CTL,
24382430 .get_optmax = EBT_SO_GET_MAX + 1,
24392431 .get = do_ebt_get_ctl,
2440
-#ifdef CONFIG_COMPAT
2441
- .compat_get = compat_do_ebt_get_ctl,
2442
-#endif
24432432 .owner = THIS_MODULE,
24442433 };
24452434