-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path0001-cgroup-add-network-limits-subsystem.patch
697 lines (684 loc) · 17.6 KB
/
0001-cgroup-add-network-limits-subsystem.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
From 1aa00f5454ac893ef25d2929dc1b16b88cf60fc2 Mon Sep 17 00:00:00 2001
From: Dmitry Kurbatov <[email protected]>
Date: Thu, 13 Aug 2015 12:07:24 +0300
Subject: [PATCH] cgroup: add network limits subsystem
---
include/linux/cgroup_subsys.h | 4 +
include/linux/net_lim_cgroup.h | 39 ++++
init/Kconfig | 5 +
kernel/Makefile | 1 +
kernel/net_lim_cgroup.c | 501 ++++++++++++++++++++++++++++++++++++++++
net/ipv4/af_inet.c | 19 +-
net/ipv4/inet_connection_sock.c | 8 +
7 files changed, 576 insertions(+), 1 deletion(-)
create mode 100644 include/linux/net_lim_cgroup.h
create mode 100644 kernel/net_lim_cgroup.c
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index e4a96fb..51e7c73 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -47,6 +47,10 @@ SUBSYS(net_prio)
SUBSYS(hugetlb)
#endif
+#if IS_ENABLED(CONFIG_CGROUP_NET_LIM)
+SUBSYS(net_lim)
+#endif
+
/*
* The following subsystems are not supported on the default hierarchy.
*/
diff --git a/include/linux/net_lim_cgroup.h b/include/linux/net_lim_cgroup.h
new file mode 100644
index 0000000..eef999b
--- /dev/null
+++ b/include/linux/net_lim_cgroup.h
@@ -0,0 +1,39 @@
+#ifndef _NET_LIM_CGROUP_H
+#define _NET_LIM_CGROUP_H
+
+#include <linux/kernel.h>
+#include <linux/threads.h>
+#include <linux/atomic.h>
+#include <linux/cgroup.h>
+#include <linux/slab.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/rwlock_types.h>
+
+struct net_lim_range_item {
+ unsigned int start, end;
+ struct list_head list;
+};
+
+struct net_lim_addr_item {
+ u32 addr;
+ struct list_head list;
+};
+
+struct net_lim_cgroup {
+ struct cgroup_subsys_state css;
+
+ /* inet_bind() available ports range */
+ struct list_head port_ranges;
+
+ /* inet_bind() available address range */
+ struct list_head addrs;
+};
+
+struct net_lim_cgroup *css_net_lim(struct cgroup_subsys_state *css);
+int net_lim_port_allowed(struct task_struct *tsk, unsigned int port);
+int net_lim_addr_allowed(struct task_struct *tsk, u32 addr);
+void net_lim_get_local_port_range(struct task_struct *tsk, int *low, int *high);
+u32 net_lim_get_default_address(struct task_struct *tsk);
+
+#endif
diff --git a/init/Kconfig b/init/Kconfig
index af09b4f..f94a361 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -949,6 +949,11 @@ config CGROUP_DEBUG
Say N if unsure.
+config CGROUP_NET_LIM
+ bool "Network limits cgroup subsystem"
+ help
+ Provides custom network limits from cgroups
+
config CGROUP_FREEZER
bool "Freezer cgroup subsystem"
help
diff --git a/kernel/Makefile b/kernel/Makefile
index 43c4c92..37a4e30 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_COMPAT) += compat.o
obj-$(CONFIG_CGROUPS) += cgroup.o
obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o
obj-$(CONFIG_CPUSETS) += cpuset.o
+obj-$(CONFIG_CGROUP_NET_LIM) += net_lim_cgroup.o
obj-$(CONFIG_UTS_NS) += utsname.o
obj-$(CONFIG_USER_NS) += user_namespace.o
obj-$(CONFIG_PID_NS) += pid_namespace.o
diff --git a/kernel/net_lim_cgroup.c b/kernel/net_lim_cgroup.c
new file mode 100644
index 0000000..123cf40
--- /dev/null
+++ b/kernel/net_lim_cgroup.c
@@ -0,0 +1,501 @@
+#include <linux/kernel.h>
+#include <linux/threads.h>
+#include <linux/atomic.h>
+#include <linux/cgroup.h>
+#include <linux/slab.h>
+#include <linux/net_lim_cgroup.h>
+#include <linux/string.h>
+
+#define RANGE_MAX_LEN 12
+#define IP_ADDRESS_MAX_LEN 16
+#define NIPQUAD(addr) \
+ ((unsigned char *)&addr)[0], \
+ ((unsigned char *)&addr)[1], \
+ ((unsigned char *)&addr)[2], \
+ ((unsigned char *)&addr)[3]
+
+static DEFINE_RWLOCK(net_lim_croup_rwlock);
+
+struct net_lim_cgroup *css_net_lim(struct cgroup_subsys_state *css)
+{
+ return container_of(css, struct net_lim_cgroup, css);
+}
+
+/*
+ * Clean list @list_ranges and deallocate all items.
+ */
+static void net_lim_range_clean(struct list_head *list_ranges)
+{
+ struct net_lim_range_item *walk, *tmp;
+
+ list_for_each_entry_safe(walk, tmp, list_ranges, list) {
+ list_del(&walk->list);
+ kfree(walk);
+ }
+}
+
+/*
+ * Clean list @list_addrs and deallocate all items.
+ */
+static void net_lim_addrs_clean(struct list_head *list_addrs)
+{
+ struct net_lim_addr_item *walk, *tmp;
+
+ list_for_each_entry_safe(walk, tmp, list_addrs, list) {
+ list_del(&walk->list);
+ kfree(walk);
+ }
+}
+
+/*
+ * Allocate new net_lim subsystem node.
+ */
+static struct cgroup_subsys_state *
+net_lim_css_alloc(struct cgroup_subsys_state *parent)
+{
+ struct net_lim_cgroup *net_lim;
+
+ net_lim = kzalloc(sizeof(struct net_lim_cgroup), GFP_KERNEL);
+ if (!net_lim)
+ return ERR_PTR(-ENOMEM);
+
+ /* initialize ports ranges. */
+ INIT_LIST_HEAD(&net_lim->port_ranges);
+
+ /* initialize addrs ranges. */
+ INIT_LIST_HEAD(&net_lim->addrs);
+
+ return &net_lim->css;
+}
+
+/*
+ * Deallocate memory of items in net_lim lists.
+ */
+static void net_lim_ranges_clean(struct net_lim_cgroup *net_lim)
+{
+ net_lim_range_clean(&net_lim->port_ranges);
+ net_lim_addrs_clean(&net_lim->addrs);
+}
+
+/*
+ * Free net_lim node.
+ */
+static void net_lim_css_free(struct cgroup_subsys_state *css)
+{
+ struct net_lim_cgroup *net_lim = css_net_lim(css);
+
+ net_lim_ranges_clean(net_lim);
+ kfree(net_lim);
+}
+
+/*
+ * Validate and extract port range string.
+ */
+static int extract_port_range(char *str, unsigned int *start, unsigned int *end)
+{
+ char *tmp = str;
+
+ if (strlen(str) > RANGE_MAX_LEN-1)
+ return -ERANGE;
+
+ if (strchr(tmp, '-') == NULL) {
+ if (kstrtoint(str, 0, (int *)start))
+ return -EINVAL;
+ *end = *start;
+ } else {
+ tmp = strsep(&str, "-");
+
+ if ((*tmp == '\0') ||
+ (str == NULL) ||
+ (*str == '\0'))
+ return -EINVAL;
+
+ if (kstrtoint(tmp, 0, (int *)start))
+ return -EINVAL;
+ if (kstrtoint(str, 0, (int *)end))
+ return -EINVAL;
+ }
+
+ if ((*end < *start) ||
+ (*start < 1) ||
+ (*start > 65535) ||
+ (*end < 1) ||
+ (*end > 65535))
+ return -ERANGE;
+
+ return 0;
+}
+
+/*
+* Validate and extract ip address from string.
+*/
+int extract_address(char *str, u32 *addr)
+{
+ const char *end;
+
+ if (strlen(str) > IP_ADDRESS_MAX_LEN-1)
+ return -EINVAL;
+
+ if (in4_pton(str, -1, (u8 *)addr, -1, &end) && !*end)
+ return 0;
+
+ return -EINVAL;
+}
+
+/*
+* Aloccate memory and add low-high range to list.
+*/
+static int list_add_range(struct list_head *list_ranges, unsigned int low,
+ unsigned int high)
+{
+ struct net_lim_range_item *range;
+
+ range = kmalloc(sizeof(*range), GFP_KERNEL);
+ if (!range)
+ return -ENOMEM;
+
+ range->start = low;
+ range->end = high;
+ list_add_tail(&range->list, list_ranges);
+ return 0;
+}
+
+/*
+* Aloccate memory and add address to list.
+*/
+static int list_add_address(struct list_head *list_addrs, u32 addr)
+{
+ struct net_lim_addr_item *addr_item;
+
+ addr_item = kmalloc(sizeof(*addr_item), GFP_KERNEL);
+ if (!addr_item)
+ return -ENOMEM;
+
+ addr_item->addr = addr;
+ list_add_tail(&addr_item->list, list_addrs);
+ return 0;
+}
+
+/*
+* Parse string of ports and ranges.
+*/
+static int parse_ports_list(char *buf, struct list_head *list_ranges)
+{
+ char *str;
+ u32 low, high;
+ int ret = 0;
+
+ while ((str = strsep(&buf, ","))) {
+ /* Extract port or region. */
+ if ((ret = extract_port_range(str, &low, &high)))
+ return ret;
+
+ if ((ret = list_add_range(list_ranges, low, high)))
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
+* Parse string of addrs.
+*/
+static int parse_addrs_list(char *buf, struct list_head *list_addrs)
+{
+ char *str;
+ u32 addr;
+ int ret = 0;
+ while ((str = strsep(&buf, ","))) {
+ /* Extract ip address from @str. */
+ if ((ret = extract_address(str, &addr)))
+ return ret;
+
+ if ((ret = list_add_address(list_addrs, addr)))
+ return ret;
+ }
+ return ret;
+}
+
+/*
+* Write list of allowed ports.
+*/
+static ssize_t net_lim_cgroup_ports_write(struct kernfs_open_file *of,
+ char *buf, size_t nbytes, loff_t off)
+{
+ int retval = 0;
+ char *buffer = strstrip(buf);
+ struct net_lim_cgroup *net_lim = css_net_lim(of_css(of));
+ LIST_HEAD(list_ranges);
+
+ if (css_has_online_children(&net_lim->css))
+ return -EINVAL;
+
+ /* Don't apply cgroup port values. */
+ if (*buffer == '\0') {
+ net_lim_range_clean(&net_lim->port_ranges);
+ return nbytes;
+ }
+
+ if ((retval = parse_ports_list(buffer, &list_ranges))) {
+ net_lim_range_clean(&list_ranges);
+ return retval;
+ }
+
+ /* Here we have valid list of port ranges. Clear existed list and
+ * replace with new one. */
+ write_lock(&net_lim_croup_rwlock);
+ net_lim_range_clean(&net_lim->port_ranges);
+ list_splice(&list_ranges, &net_lim->port_ranges);
+ write_unlock(&net_lim_croup_rwlock);
+ return nbytes;
+}
+
+/*
+* Show list of allowed ports.
+*/
+static int net_lim_cgroup_ports_seq_show(struct seq_file *seq, void *v)
+{
+ struct net_lim_range_item *walk;
+ struct cgroup_subsys_state *css = seq_css(seq);
+ struct net_lim_cgroup *net_lim = css_net_lim(css);
+ int comma = 0;
+
+ read_lock(&net_lim_croup_rwlock);
+ list_for_each_entry(walk, &net_lim->port_ranges, list) {
+ if (comma++)
+ seq_printf(seq, ",");
+ if (walk->start == walk->end) {
+ seq_printf(seq, "%d", walk->start);
+ } else {
+ seq_printf(seq, "%d-%d", walk->start, walk->end);
+ }
+ }
+ read_unlock(&net_lim_croup_rwlock);
+ if (comma)
+ seq_printf(seq, "\n");
+ return 0;
+}
+
+/*
+* Show current local_port_range value.
+*/
+static int net_lim_cgroup_local_port_range_seq_show(struct seq_file *seq,
+ void *v)
+{
+ struct net_lim_cgroup *net_lim = css_net_lim(seq_css(seq));
+ struct net_lim_range_item *range;
+
+ read_lock(&net_lim_croup_rwlock);
+ if (list_empty(&net_lim->port_ranges))
+ goto _unlock;
+
+ range = list_last_entry(&net_lim->port_ranges,
+ struct net_lim_range_item, list);
+
+ seq_printf(seq, "%d-%d\n", range->start, range->end);
+
+_unlock:
+ read_unlock(&net_lim_croup_rwlock);
+ return 0;
+}
+
+/*
+* Write list of allowed addrs.
+*/
+static ssize_t net_lim_cgroup_addrs_write(struct kernfs_open_file *of,
+ char *buf, size_t nbytes, loff_t off)
+{
+ int retval = 0;
+ char *buffer = strstrip(buf);
+ struct net_lim_cgroup *net_lim = css_net_lim(of_css(of));
+ LIST_HEAD(list_addrs);
+
+ if (css_has_online_children(&net_lim->css))
+ return -EINVAL;
+
+ /* Don't apply cgroup values to limit bind() addresses. */
+ if (*buffer == '\0') {
+ net_lim_addrs_clean(&net_lim->addrs);
+ // net_lim_list_clean(&net_lim->addrs, walk, tmp);
+ return nbytes;
+ }
+
+ if ((retval = parse_addrs_list(buffer, &list_addrs))) {
+ net_lim_addrs_clean(&list_addrs);
+ return retval;
+ }
+
+ /* Here we have valid list of addrs. Clear existed list and
+ * replace with new one. */
+ write_lock(&net_lim_croup_rwlock);
+ net_lim_addrs_clean(&net_lim->addrs);
+ list_splice(&list_addrs, &net_lim->addrs);
+ write_unlock(&net_lim_croup_rwlock);
+ return nbytes;
+}
+
+/*
+* Show list of allowed addrs.
+*/
+static int net_lim_cgroup_addrs_seq_show(struct seq_file *seq, void *v)
+{
+ struct net_lim_addr_item *walk;
+ struct net_lim_cgroup *net_lim = css_net_lim(seq_css(seq));
+ int wrote = 0;
+
+ read_lock(&net_lim_croup_rwlock);
+ list_for_each_entry(walk, &net_lim->addrs, list) {
+ if (wrote++)
+ seq_printf(seq, ",");
+ seq_printf(seq, "%d.%d.%d.%d", NIPQUAD(walk->addr));
+ }
+ if (wrote)
+ seq_printf(seq, "\n");
+ read_unlock(&net_lim_croup_rwlock);
+ return 0;
+}
+
+/*
+* Show current default_address value.
+*/
+static int net_lim_cgroup_default_address_seq_show(struct seq_file *seq,
+ void *v)
+{
+ struct net_lim_cgroup *net_lim = css_net_lim(seq_css(seq));
+ struct net_lim_addr_item *addr_item = NULL;
+
+ read_lock(&net_lim_croup_rwlock);
+ if (list_empty(&net_lim->addrs))
+ goto _unlock;
+
+ addr_item = list_first_entry(&net_lim->addrs, struct net_lim_addr_item, list);
+ seq_printf(seq, "%d.%d.%d.%d\n", NIPQUAD(addr_item->addr));
+
+_unlock:
+ read_unlock(&net_lim_croup_rwlock);
+ return 0;
+}
+
+
+static struct cftype net_lim_files[] = {
+ {
+ .name = "ipv4.ports",
+ .write = net_lim_cgroup_ports_write,
+ .seq_show = net_lim_cgroup_ports_seq_show,
+ },
+ {
+ .name = "ipv4.ip_local_port_range",
+ .seq_show = net_lim_cgroup_local_port_range_seq_show,
+ },
+ {
+ .name = "ipv4.addrs",
+ .write = net_lim_cgroup_addrs_write,
+ .seq_show = net_lim_cgroup_addrs_seq_show,
+ },
+ {
+ .name = "ipv4.default_address",
+ .seq_show = net_lim_cgroup_default_address_seq_show,
+ },
+ { } /* terminate */
+};
+
+struct cgroup_subsys net_lim_cgrp_subsys = {
+ .css_alloc = net_lim_css_alloc,
+ .css_free = net_lim_css_free,
+ .legacy_cftypes = net_lim_files,
+ .dfl_cftypes = net_lim_files,
+};
+
+int net_lim_port_allowed(struct task_struct *tsk, unsigned int port)
+{
+ struct net_lim_cgroup *net_lim =
+ css_net_lim(tsk->cgroups->subsys[net_lim_cgrp_id]);
+ struct net_lim_range_item *walk;
+ int found = 0;
+
+ read_lock(&net_lim_croup_rwlock);
+ /* Don't apply cgroup rules if list is empty. */
+ if (list_empty(&net_lim->port_ranges)) {
+ found++;
+ goto _unlock;
+ }
+ /* Check in list of ranges for allowed port. */
+ list_for_each_entry(walk, &net_lim->port_ranges, list) {
+ if ((walk->start <= port) && (port <= walk->end)) {
+ found++;
+ goto _unlock;
+ }
+ }
+_unlock:
+ read_unlock(&net_lim_croup_rwlock);
+ return found;
+}
+
+int net_lim_addr_allowed(struct task_struct *tsk, u32 addr)
+{
+ struct net_lim_cgroup *net_lim =
+ css_net_lim(tsk->cgroups->subsys[net_lim_cgrp_id]);
+ struct net_lim_addr_item *walk;
+ int found = 0;
+
+ read_lock(&net_lim_croup_rwlock);
+ /* Don't apply cgroup rules if list is empty. */
+ if (list_empty(&net_lim->addrs)) {
+ found++;
+ goto _unlock;
+ }
+ /* Check in list of addrs for allowed addr. */
+ list_for_each_entry(walk, &net_lim->addrs, list) {
+ if (walk->addr == addr) {
+ found++;
+ goto _unlock;
+ }
+ }
+_unlock:
+ read_unlock(&net_lim_croup_rwlock);
+ return found;
+}
+
+void net_lim_get_local_port_range(struct task_struct *tsk, int *low, int *high)
+{
+ struct net_lim_cgroup *net_lim =
+ css_net_lim(tsk->cgroups->subsys[net_lim_cgrp_id]);
+ struct net_lim_range_item *range;
+
+ read_lock(&net_lim_croup_rwlock);
+ if (list_empty(&net_lim->port_ranges))
+ goto _unlock;
+
+ /* Use net_lim range values if list of allowed ports is not empty. */
+ range = list_last_entry(&net_lim->port_ranges,
+ struct net_lim_range_item, list);
+
+ *low = range->start;
+ *high = range->end;
+
+_unlock:
+ read_unlock(&net_lim_croup_rwlock);
+}
+
+u32 net_lim_get_default_address(struct task_struct *tsk)
+{
+ struct net_lim_cgroup *net_lim =
+ css_net_lim(tsk->cgroups->subsys[net_lim_cgrp_id]);
+ u32 addr;
+ struct net_lim_addr_item *addr_item;
+
+
+ read_lock(&net_lim_croup_rwlock);
+ if (list_empty(&net_lim->addrs)) {
+ addr = 0;
+ goto _unlock;
+ }
+
+ /* Use net_lim range values if list of allowed ports is not empty. */
+ addr_item = list_first_entry(&net_lim->addrs, struct net_lim_addr_item,
+ list);
+ addr = addr_item->addr;
+_unlock:
+ read_unlock(&net_lim_croup_rwlock);
+ return addr;
+}
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 9532ee8..e10ff09 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -119,6 +119,9 @@
#include <linux/mroute.h>
#endif
+#ifdef CONFIG_CGROUP_NET_LIM
+#include <linux/net_lim_cgroup.h>
+#endif
/* The inetsw table contains everything that inet_create needs to
* build a new socket.
@@ -427,7 +430,12 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
unsigned short snum;
int chk_addr_ret;
int err;
+#ifdef CONFIG_CGROUP_NET_LIM
+ u32 def_addr = net_lim_get_default_address(get_current());
+ if (def_addr != 0 && addr->sin_addr.s_addr == htonl(INADDR_ANY))
+ addr->sin_addr.s_addr = def_addr;
+#endif
/* If the socket has its own bind function then use it. (RAW) */
if (sk->sk_prot->bind) {
err = sk->sk_prot->bind(sk, uaddr, addr_len);
@@ -467,6 +475,16 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
snum = ntohs(addr->sin_port);
err = -EACCES;
+#ifdef CONFIG_CGROUP_NET_LIM
+ // if (snum == 0 && !net_lim_zero_port_allowed(get_current()))
+ // goto out;
+
+ if (snum !=0 && !net_lim_port_allowed(get_current(), snum))
+ goto out;
+
+ if (!net_lim_addr_allowed(get_current(), addr->sin_addr.s_addr))
+ goto out;
+#endif
if (snum && snum < PROT_SOCK &&
!ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
goto out;
@@ -1834,4 +1852,3 @@ static int __init ipv4_proc_init(void)
#endif /* CONFIG_PROC_FS */
MODULE_ALIAS_NETPROTO(PF_INET);
-
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 60021d0..bb614d7 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -6,6 +6,7 @@
* Support for INET connection oriented protocols.
*
* Authors: See the TCP sources
+ * TODO: ret
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,6 +25,9 @@
#include <net/tcp_states.h>
#include <net/xfrm.h>
#include <net/tcp.h>
+#ifdef CONFIG_CGROUP_NET_LIM
+#include <linux/net_lim_cgroup.h>
+#endif
#ifdef INET_CSK_DEBUG
const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n";
@@ -40,6 +44,10 @@ void inet_get_local_port_range(struct net *net, int *low, int *high)
*low = net->ipv4.ip_local_ports.range[0];
*high = net->ipv4.ip_local_ports.range[1];
} while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq));
+#ifdef CONFIG_CGROUP_NET_LIM
+ net_lim_get_local_port_range(get_current(), low, high);
+#endif
+
}
EXPORT_SYMBOL(inet_get_local_port_range);
--
2.1.0