diff options
| author | Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | 2021-09-22 21:08:08 +0530 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-10-07 15:10:33 +0100 |
| commit | f3452bf99367ed2270a4deb47e6f03039af7d39d (patch) | |
| tree | 4f843091972e2297f6f67809c7eec1c68dab761f | |
| parent | 3d5a3e009a6ff92b16ab205ec9123f52fca23c77 (diff) | |
| download | poky-f3452bf99367ed2270a4deb47e6f03039af7d39d.tar.gz | |
systemd: Add fix for systemd-networkd crash during free
We are observing systemd-network service crash during link down
while freeing link->ifname pointer
Backtrace:
(gdb) bt
0 __GI_abort () at abort.c:107
1 0x0000007f861d32b4 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f8628d500 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
2 0x0000007f861da51c in malloc_printerr (str=str@entry=0x7f86289070 "free(): invalid next size (fast)") at malloc.c:5347
3 0x0000007f861dbd58 in _int_free (av=0x7f862c9a28 <main_arena>, p=0x558aa28eb0, have_lock=0) at malloc.c:4249
4 0x0000005569249cf0 in link_free (link=0x558aa1c0d0) at ../git/src/network/networkd-link.c:715
5 link_unref (p=0x558aa1c0d0) at ../git/src/network/networkd-link.c:734
6 0x000000556920f34c in manager_rtnl_process_link (rtnl=<optimized out>, message=0x558aa2a430, userdata=0x558a9fc630)
While checking upstream code change with regards to link->ifname
memory allocation and free, we found below PR which also fixes
random systemd-networkd crash:
https://github.com/systemd/systemd/pull/19631
https://github.com/systemd/systemd/issues/19629
(From OE-Core rev: adca61c61d84f022fdedd2d616e7c2df00661af8)
Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
Signed-off-by: Ranjitsinh Rathod <ranjitsinhrathod1991@gmail.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
7 files changed, 799 insertions, 0 deletions
diff --git a/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch new file mode 100644 index 0000000000..86d9b0499a --- /dev/null +++ b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | From 1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||
| 3 | Date: Tue, 1 Sep 2020 12:42:35 +0200 | ||
| 4 | Subject: [PATCH] basic: pass allocation info for ordered_set_new() and | ||
| 5 | introduce ordered_set_ensure_put() | ||
| 6 | |||
| 7 | Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1] | ||
| 8 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
| 9 | |||
| 10 | --- | ||
| 11 | src/basic/ordered-set.c | 21 +++++++++++++++++++++ | ||
| 12 | src/basic/ordered-set.h | 18 +++++++----------- | ||
| 13 | 2 files changed, 28 insertions(+), 11 deletions(-) | ||
| 14 | |||
| 15 | diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c | ||
| 16 | index 7fdb47e064..fb82c17b5a 100644 | ||
| 17 | --- a/src/basic/ordered-set.c | ||
| 18 | +++ b/src/basic/ordered-set.c | ||
| 19 | @@ -4,6 +4,27 @@ | ||
| 20 | #include "ordered-set.h" | ||
| 21 | #include "strv.h" | ||
| 22 | |||
| 23 | +int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) { | ||
| 24 | + if (*s) | ||
| 25 | + return 0; | ||
| 26 | + | ||
| 27 | + *s = _ordered_set_new(ops HASHMAP_DEBUG_PASS_ARGS); | ||
| 28 | + if (!*s) | ||
| 29 | + return -ENOMEM; | ||
| 30 | + | ||
| 31 | + return 0; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS) { | ||
| 35 | + int r; | ||
| 36 | + | ||
| 37 | + r = _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_PASS_ARGS); | ||
| 38 | + if (r < 0) | ||
| 39 | + return r; | ||
| 40 | + | ||
| 41 | + return ordered_set_put(*s, p); | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | int ordered_set_consume(OrderedSet *s, void *p) { | ||
| 45 | int r; | ||
| 46 | |||
| 47 | diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h | ||
| 48 | index a42a57eb49..2c241a808b 100644 | ||
| 49 | --- a/src/basic/ordered-set.h | ||
| 50 | +++ b/src/basic/ordered-set.h | ||
| 51 | @@ -7,20 +7,16 @@ | ||
| 52 | |||
| 53 | typedef struct OrderedSet OrderedSet; | ||
| 54 | |||
| 55 | -static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) { | ||
| 56 | - return (OrderedSet*) ordered_hashmap_new(ops); | ||
| 57 | +static inline OrderedSet* _ordered_set_new(const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) { | ||
| 58 | + return (OrderedSet*) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_PASS_ARGS); | ||
| 59 | } | ||
| 60 | +#define ordered_set_new(ops) _ordered_set_new(ops HASHMAP_DEBUG_SRC_ARGS) | ||
| 61 | |||
| 62 | -static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) { | ||
| 63 | - if (*s) | ||
| 64 | - return 0; | ||
| 65 | +int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS); | ||
| 66 | +#define ordered_set_ensure_allocated(s, ops) _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_SRC_ARGS) | ||
| 67 | |||
| 68 | - *s = ordered_set_new(ops); | ||
| 69 | - if (!*s) | ||
| 70 | - return -ENOMEM; | ||
| 71 | - | ||
| 72 | - return 0; | ||
| 73 | -} | ||
| 74 | +int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS); | ||
| 75 | +#define ordered_set_ensure_put(s, hash_ops, key) _ordered_set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS) | ||
| 76 | |||
| 77 | static inline OrderedSet* ordered_set_free(OrderedSet *s) { | ||
| 78 | return (OrderedSet*) ordered_hashmap_free((OrderedHashmap*) s); | ||
diff --git a/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch new file mode 100644 index 0000000000..42b6e05b55 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | From d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||
| 3 | Date: Mon, 26 Apr 2021 23:52:40 +0900 | ||
| 4 | Subject: [PATCH] ordered-set: introduce | ||
| 5 | ordered_set_clear/free_with_destructor() | ||
| 6 | |||
| 7 | Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5] | ||
| 8 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
| 9 | |||
| 10 | --- | ||
| 11 | src/basic/ordered-set.h | 11 +++++++++++ | ||
| 12 | 1 file changed, 11 insertions(+) | ||
| 13 | |||
| 14 | diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h | ||
| 15 | index a377f20b1f..64df41766f 100644 | ||
| 16 | --- a/src/basic/ordered-set.h | ||
| 17 | +++ b/src/basic/ordered-set.h | ||
| 18 | @@ -63,6 +63,17 @@ void ordered_set_print(FILE *f, const char *field, OrderedSet *s); | ||
| 19 | #define ORDERED_SET_FOREACH(e, s, i) \ | ||
| 20 | for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); ) | ||
| 21 | |||
| 22 | +#define ordered_set_clear_with_destructor(s, f) \ | ||
| 23 | + ({ \ | ||
| 24 | + OrderedSet *_s = (s); \ | ||
| 25 | + void *_item; \ | ||
| 26 | + while ((_item = ordered_set_steal_first(_s))) \ | ||
| 27 | + f(_item); \ | ||
| 28 | + _s; \ | ||
| 29 | + }) | ||
| 30 | +#define ordered_set_free_with_destructor(s, f) \ | ||
| 31 | + ordered_set_free(ordered_set_clear_with_destructor(s, f)) | ||
| 32 | + | ||
| 33 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); | ||
| 34 | DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); | ||
| 35 | |||
diff --git a/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch new file mode 100644 index 0000000000..06c523834d --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch | |||
| @@ -0,0 +1,285 @@ | |||
| 1 | From 19d9a5adf0c1a6b5a243eea0390f6f6526d569de Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||
| 3 | Date: Fri, 7 May 2021 15:39:16 +0900 | ||
| 4 | Subject: [PATCH] network: add skeleton of request queue | ||
| 5 | |||
| 6 | This will be used in later commits. | ||
| 7 | |||
| 8 | Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/19d9a5adf0c1a6b5a243eea0390f6f6526d569de] | ||
| 9 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
| 10 | |||
| 11 | --- | ||
| 12 | src/network/meson.build | 2 + | ||
| 13 | src/network/networkd-link.c | 20 +++++- | ||
| 14 | src/network/networkd-manager.c | 7 ++ | ||
| 15 | src/network/networkd-manager.h | 2 + | ||
| 16 | src/network/networkd-queue.c | 121 +++++++++++++++++++++++++++++++++ | ||
| 17 | src/network/networkd-queue.h | 42 ++++++++++++ | ||
| 18 | 6 files changed, 192 insertions(+), 2 deletions(-) | ||
| 19 | create mode 100644 src/network/networkd-queue.c | ||
| 20 | create mode 100644 src/network/networkd-queue.h | ||
| 21 | |||
| 22 | diff --git a/src/network/meson.build b/src/network/meson.build | ||
| 23 | index 4fca3106dc..a8b9232e64 100644 | ||
| 24 | --- a/src/network/meson.build | ||
| 25 | +++ b/src/network/meson.build | ||
| 26 | @@ -105,6 +105,8 @@ sources = files(''' | ||
| 27 | networkd-network.h | ||
| 28 | networkd-nexthop.c | ||
| 29 | networkd-nexthop.h | ||
| 30 | + networkd-queue.c | ||
| 31 | + networkd-queue.h | ||
| 32 | networkd-route.c | ||
| 33 | networkd-route.h | ||
| 34 | networkd-routing-policy-rule.c | ||
| 35 | diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c | ||
| 36 | index 34359b2541..2f33305a27 100644 | ||
| 37 | --- a/src/network/networkd-link.c | ||
| 38 | +++ b/src/network/networkd-link.c | ||
| 39 | @@ -30,6 +30,7 @@ | ||
| 40 | #include "networkd-manager.h" | ||
| 41 | #include "networkd-ndisc.h" | ||
| 42 | #include "networkd-neighbor.h" | ||
| 43 | +#include "networkd-queue.h" | ||
| 44 | #include "networkd-radv.h" | ||
| 45 | #include "networkd-routing-policy-rule.h" | ||
| 46 | #include "networkd-wifi.h" | ||
| 47 | |||
| 48 | @@ -2232,6 +2244,8 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for | ||
| 49 | if (r < 0) | ||
| 50 | return r; | ||
| 51 | |||
| 52 | + link_drop_requests(link); | ||
| 53 | + | ||
| 54 | r = link_drop_config(link); | ||
| 55 | if (r < 0) | ||
| 56 | return r; | ||
| 57 | @@ -2664,6 +2678,8 @@ static int link_carrier_lost(Link *link) { | ||
| 58 | return r; | ||
| 59 | } | ||
| 60 | |||
| 61 | + link_drop_requests(link); | ||
| 62 | + | ||
| 63 | r = link_drop_config(link); | ||
| 64 | if (r < 0) | ||
| 65 | return r; | ||
| 66 | diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c | ||
| 67 | index 562ce5ca54..fd576169a9 100644 | ||
| 68 | --- a/src/network/networkd-manager.c | ||
| 69 | +++ b/src/network/networkd-manager.c | ||
| 70 | @@ -34,6 +34,7 @@ | ||
| 71 | #include "networkd-manager-bus.h" | ||
| 72 | #include "networkd-manager.h" | ||
| 73 | #include "networkd-network-bus.h" | ||
| 74 | +#include "networkd-queue.h" | ||
| 75 | #include "networkd-speed-meter.h" | ||
| 76 | #include "ordered-set.h" | ||
| 77 | #include "path-util.h" | ||
| 78 | @@ -406,6 +407,10 @@ int manager_new(Manager **ret) { | ||
| 79 | if (r < 0) | ||
| 80 | return r; | ||
| 81 | |||
| 82 | + r = sd_event_add_post(m->event, NULL, manager_process_requests, m); | ||
| 83 | + if (r < 0) | ||
| 84 | + return r; | ||
| 85 | + | ||
| 86 | r = manager_connect_rtnl(m); | ||
| 87 | if (r < 0) | ||
| 88 | return r; | ||
| 89 | @@ -446,6 +451,8 @@ Manager* manager_free(Manager *m) { | ||
| 90 | |||
| 91 | free(m->state_file); | ||
| 92 | |||
| 93 | + m->request_queue = ordered_set_free_with_destructor(m->request_queue, request_free); | ||
| 94 | + | ||
| 95 | while ((a = hashmap_first_key(m->dhcp6_prefixes))) | ||
| 96 | (void) dhcp6_prefix_remove(m, a); | ||
| 97 | m->dhcp6_prefixes = hashmap_free(m->dhcp6_prefixes); | ||
| 98 | diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h | ||
| 99 | index 301b97c1a1..26e8802871 100644 | ||
| 100 | --- a/src/network/networkd-manager.h | ||
| 101 | +++ b/src/network/networkd-manager.h | ||
| 102 | @@ -91,6 +91,8 @@ struct Manager { | ||
| 103 | usec_t speed_meter_usec_old; | ||
| 104 | |||
| 105 | bool dhcp4_prefix_root_cannot_set_table; | ||
| 106 | + | ||
| 107 | + OrderedSet *request_queue; | ||
| 108 | }; | ||
| 109 | |||
| 110 | int manager_new(Manager **ret); | ||
| 111 | diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c | ||
| 112 | new file mode 100644 | ||
| 113 | index 0000000000..24bb2c845d | ||
| 114 | --- /dev/null | ||
| 115 | +++ b/src/network/networkd-queue.c | ||
| 116 | @@ -0,0 +1,121 @@ | ||
| 117 | +/* SPDX-License-Identifier: LGPL-2.1-or-later */ | ||
| 118 | + | ||
| 119 | +#include "networkd-address.h" | ||
| 120 | +#include "networkd-manager.h" | ||
| 121 | +#include "networkd-neighbor.h" | ||
| 122 | +#include "networkd-nexthop.h" | ||
| 123 | +#include "networkd-route.h" | ||
| 124 | +#include "networkd-routing-policy-rule.h" | ||
| 125 | +#include "networkd-queue.h" | ||
| 126 | + | ||
| 127 | +static void request_free_object(RequestType type, void *object) { | ||
| 128 | + switch(type) { | ||
| 129 | + default: | ||
| 130 | + assert_not_reached("invalid request type."); | ||
| 131 | + } | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +Request *request_free(Request *req) { | ||
| 135 | + if (!req) | ||
| 136 | + return NULL; | ||
| 137 | + | ||
| 138 | + if (req->on_free) | ||
| 139 | + req->on_free(req); | ||
| 140 | + if (req->consume_object) | ||
| 141 | + request_free_object(req->type, req->object); | ||
| 142 | + if (req->link && req->link->manager) | ||
| 143 | + ordered_set_remove(req->link->manager->request_queue, req); | ||
| 144 | + link_unref(req->link); | ||
| 145 | + | ||
| 146 | + return mfree(req); | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free); | ||
| 150 | + | ||
| 151 | +void request_drop(Request *req) { | ||
| 152 | + if (req->message_counter) | ||
| 153 | + (*req->message_counter)--; | ||
| 154 | + | ||
| 155 | + request_free(req); | ||
| 156 | +} | ||
| 157 | + | ||
| 158 | +int link_queue_request( | ||
| 159 | + Link *link, | ||
| 160 | + RequestType type, | ||
| 161 | + void *object, | ||
| 162 | + bool consume_object, | ||
| 163 | + unsigned *message_counter, | ||
| 164 | + link_netlink_message_handler_t netlink_handler, | ||
| 165 | + Request **ret) { | ||
| 166 | + | ||
| 167 | + _cleanup_(request_freep) Request *req = NULL; | ||
| 168 | + int r; | ||
| 169 | + | ||
| 170 | + assert(link); | ||
| 171 | + assert(link->manager); | ||
| 172 | + assert(type >= 0 && type < _REQUEST_TYPE_MAX); | ||
| 173 | + assert(object); | ||
| 174 | + assert(netlink_handler); | ||
| 175 | + | ||
| 176 | + req = new(Request, 1); | ||
| 177 | + if (!req) { | ||
| 178 | + if (consume_object) | ||
| 179 | + request_free_object(type, object); | ||
| 180 | + return -ENOMEM; | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + *req = (Request) { | ||
| 184 | + .link = link, | ||
| 185 | + .type = type, | ||
| 186 | + .object = object, | ||
| 187 | + .consume_object = consume_object, | ||
| 188 | + .message_counter = message_counter, | ||
| 189 | + .netlink_handler = netlink_handler, | ||
| 190 | + }; | ||
| 191 | + | ||
| 192 | + link_ref(link); | ||
| 193 | + | ||
| 194 | + r = ordered_set_ensure_put(&link->manager->request_queue, NULL, req); | ||
| 195 | + if (r < 0) | ||
| 196 | + return r; | ||
| 197 | + | ||
| 198 | + if (req->message_counter) | ||
| 199 | + (*req->message_counter)++; | ||
| 200 | + | ||
| 201 | + if (ret) | ||
| 202 | + *ret = req; | ||
| 203 | + | ||
| 204 | + TAKE_PTR(req); | ||
| 205 | + return 0; | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +int manager_process_requests(sd_event_source *s, void *userdata) { | ||
| 209 | + Manager *manager = userdata; | ||
| 210 | + int r; | ||
| 211 | + | ||
| 212 | + assert(manager); | ||
| 213 | + | ||
| 214 | + for (;;) { | ||
| 215 | + bool processed = false; | ||
| 216 | + Request *req; | ||
| 217 | + Iterator i; | ||
| 218 | + ORDERED_SET_FOREACH(req, manager->request_queue, i) { | ||
| 219 | + switch(req->type) { | ||
| 220 | + default: | ||
| 221 | + return -EINVAL; | ||
| 222 | + } | ||
| 223 | + if (r < 0) | ||
| 224 | + link_enter_failed(req->link); | ||
| 225 | + if (r > 0) { | ||
| 226 | + ordered_set_remove(manager->request_queue, req); | ||
| 227 | + request_free(req); | ||
| 228 | + processed = true; | ||
| 229 | + } | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + if (!processed) | ||
| 233 | + break; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + return 0; | ||
| 237 | +} | ||
| 238 | diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h | ||
| 239 | new file mode 100644 | ||
| 240 | index 0000000000..4558ae548f | ||
| 241 | --- /dev/null | ||
| 242 | +++ b/src/network/networkd-queue.h | ||
| 243 | @@ -0,0 +1,42 @@ | ||
| 244 | +/* SPDX-License-Identifier: LGPL-2.1-or-later */ | ||
| 245 | +#pragma once | ||
| 246 | + | ||
| 247 | +#include "sd-event.h" | ||
| 248 | + | ||
| 249 | +#include "networkd-link.h" | ||
| 250 | + | ||
| 251 | +typedef struct Request Request; | ||
| 252 | + | ||
| 253 | +typedef int (*request_after_configure_handler_t)(Request*, void*); | ||
| 254 | +typedef void (*request_on_free_handler_t)(Request*); | ||
| 255 | + | ||
| 256 | +typedef enum RequestType { | ||
| 257 | + _REQUEST_TYPE_MAX, | ||
| 258 | + _REQUEST_TYPE_INVALID = -EINVAL, | ||
| 259 | +} RequestType; | ||
| 260 | + | ||
| 261 | +typedef struct Request { | ||
| 262 | + Link *link; | ||
| 263 | + RequestType type; | ||
| 264 | + bool consume_object; | ||
| 265 | + void *object; | ||
| 266 | + void *userdata; | ||
| 267 | + unsigned *message_counter; | ||
| 268 | + link_netlink_message_handler_t netlink_handler; | ||
| 269 | + request_after_configure_handler_t after_configure; | ||
| 270 | + request_on_free_handler_t on_free; | ||
| 271 | +} Request; | ||
| 272 | + | ||
| 273 | +Request *request_free(Request *req); | ||
| 274 | +void request_drop(Request *req); | ||
| 275 | + | ||
| 276 | +int link_queue_request( | ||
| 277 | + Link *link, | ||
| 278 | + RequestType type, | ||
| 279 | + void *object, | ||
| 280 | + bool consume_object, | ||
| 281 | + unsigned *message_counter, | ||
| 282 | + link_netlink_message_handler_t netlink_handler, | ||
| 283 | + Request **ret); | ||
| 284 | + | ||
| 285 | +int manager_process_requests(sd_event_source *s, void *userdata); | ||
diff --git a/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch new file mode 100644 index 0000000000..4c402e7e55 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | From 56001f023305ea99329e27141d6e6067596491a9 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||
| 3 | Date: Mon, 17 May 2021 15:32:57 +0900 | ||
| 4 | Subject: [PATCH] network: also drop requests when link enters linger state | ||
| 5 | |||
| 6 | Otherwise, if link is removed, several references to the link in remain | ||
| 7 | exist in requests. | ||
| 8 | |||
| 9 | Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/56001f023305ea99329e27141d6e6067596491a9] | ||
| 10 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
| 11 | |||
| 12 | --- | ||
| 13 | src/network/networkd-link.c | 24 +++++++++++++----------- | ||
| 14 | 1 file changed, 13 insertions(+), 11 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c | ||
| 17 | index 67d01ac44d..b56c232eca 100644 | ||
| 18 | --- a/src/network/networkd-link.c | ||
| 19 | +++ b/src/network/networkd-link.c | ||
| 20 | @@ -1771,6 +1771,18 @@ static void link_drop_from_master(Link *link, NetDev *netdev) { | ||
| 21 | link_unref(set_remove(master->slaves, link)); | ||
| 22 | } | ||
| 23 | |||
| 24 | +static void link_drop_requests(Link *link) { | ||
| 25 | + Request *req; | ||
| 26 | + Iterator i; | ||
| 27 | + | ||
| 28 | + assert(link); | ||
| 29 | + assert(link->manager); | ||
| 30 | + | ||
| 31 | + ORDERED_SET_FOREACH(req, link->manager->request_queue, i) | ||
| 32 | + if (req->link == link) | ||
| 33 | + request_drop(req); | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | void link_drop(Link *link) { | ||
| 37 | if (!link) | ||
| 38 | return; | ||
| 39 | @@ -1782,6 +1793,8 @@ void link_drop(Link *link) { | ||
| 40 | /* Drop all references from other links and manager. Note that async netlink calls may have | ||
| 41 | * references to the link, and they will be dropped when we receive replies. */ | ||
| 42 | |||
| 43 | + link_drop_requests(link); | ||
| 44 | + | ||
| 45 | link_free_carrier_maps(link); | ||
| 46 | |||
| 47 | if (link->network) { | ||
| 48 | -- | ||
| 49 | 2.17.1 | ||
| 50 | |||
diff --git a/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch new file mode 100644 index 0000000000..a186bb4095 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch | |||
| @@ -0,0 +1,278 @@ | |||
| 1 | From cc2d7efc5ca09a7de4bec55e80476986839a655c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||
| 3 | Date: Fri, 14 May 2021 15:58:15 +0900 | ||
| 4 | Subject: [PATCH] network: fix Link reference counter issue | ||
| 5 | |||
| 6 | Previously, when link_new() fails, `link_unref()` was called, so, | ||
| 7 | `Manager::links` may become dirty. | ||
| 8 | This introduces `link_drop_or_unref()` and it will be called on | ||
| 9 | failure. | ||
| 10 | |||
| 11 | Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/cc2d7efc5ca09a7de4bec55e80476986839a655c] | ||
| 12 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
| 13 | |||
| 14 | --- | ||
| 15 | src/network/networkd-link.c | 240 ++++++++++++++++++------------------ | ||
| 16 | 1 file changed, 122 insertions(+), 118 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c | ||
| 19 | index b56c232eca..d493afda4c 100644 | ||
| 20 | --- a/src/network/networkd-link.c | ||
| 21 | +++ b/src/network/networkd-link.c | ||
| 22 | @@ -540,109 +540,6 @@ static int link_update_flags(Link *link, | ||
| 23 | return 0; | ||
| 24 | } | ||
| 25 | |||
| 26 | -static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { | ||
| 27 | - _cleanup_(link_unrefp) Link *link = NULL; | ||
| 28 | - uint16_t type; | ||
| 29 | - const char *ifname, *kind = NULL; | ||
| 30 | - int r, ifindex; | ||
| 31 | - unsigned short iftype; | ||
| 32 | - | ||
| 33 | - assert(manager); | ||
| 34 | - assert(message); | ||
| 35 | - assert(ret); | ||
| 36 | - | ||
| 37 | - /* check for link kind */ | ||
| 38 | - r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); | ||
| 39 | - if (r == 0) { | ||
| 40 | - (void) sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind); | ||
| 41 | - r = sd_netlink_message_exit_container(message); | ||
| 42 | - if (r < 0) | ||
| 43 | - return r; | ||
| 44 | - } | ||
| 45 | - | ||
| 46 | - r = sd_netlink_message_get_type(message, &type); | ||
| 47 | - if (r < 0) | ||
| 48 | - return r; | ||
| 49 | - else if (type != RTM_NEWLINK) | ||
| 50 | - return -EINVAL; | ||
| 51 | - | ||
| 52 | - r = sd_rtnl_message_link_get_ifindex(message, &ifindex); | ||
| 53 | - if (r < 0) | ||
| 54 | - return r; | ||
| 55 | - else if (ifindex <= 0) | ||
| 56 | - return -EINVAL; | ||
| 57 | - | ||
| 58 | - r = sd_rtnl_message_link_get_type(message, &iftype); | ||
| 59 | - if (r < 0) | ||
| 60 | - return r; | ||
| 61 | - | ||
| 62 | - r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname); | ||
| 63 | - if (r < 0) | ||
| 64 | - return r; | ||
| 65 | - | ||
| 66 | - link = new(Link, 1); | ||
| 67 | - if (!link) | ||
| 68 | - return -ENOMEM; | ||
| 69 | - | ||
| 70 | - *link = (Link) { | ||
| 71 | - .n_ref = 1, | ||
| 72 | - .manager = manager, | ||
| 73 | - .state = LINK_STATE_PENDING, | ||
| 74 | - .ifindex = ifindex, | ||
| 75 | - .iftype = iftype, | ||
| 76 | - | ||
| 77 | - .n_dns = (unsigned) -1, | ||
| 78 | - .dns_default_route = -1, | ||
| 79 | - .llmnr = _RESOLVE_SUPPORT_INVALID, | ||
| 80 | - .mdns = _RESOLVE_SUPPORT_INVALID, | ||
| 81 | - .dnssec_mode = _DNSSEC_MODE_INVALID, | ||
| 82 | - .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID, | ||
| 83 | - }; | ||
| 84 | - | ||
| 85 | - link->ifname = strdup(ifname); | ||
| 86 | - if (!link->ifname) | ||
| 87 | - return -ENOMEM; | ||
| 88 | - | ||
| 89 | - if (kind) { | ||
| 90 | - link->kind = strdup(kind); | ||
| 91 | - if (!link->kind) | ||
| 92 | - return -ENOMEM; | ||
| 93 | - } | ||
| 94 | - | ||
| 95 | - r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex); | ||
| 96 | - if (r < 0) | ||
| 97 | - log_link_debug_errno(link, r, "New device has no master, continuing without"); | ||
| 98 | - | ||
| 99 | - r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); | ||
| 100 | - if (r < 0) | ||
| 101 | - log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); | ||
| 102 | - | ||
| 103 | - if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) | ||
| 104 | - return -ENOMEM; | ||
| 105 | - | ||
| 106 | - if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) | ||
| 107 | - return -ENOMEM; | ||
| 108 | - | ||
| 109 | - if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) | ||
| 110 | - return -ENOMEM; | ||
| 111 | - | ||
| 112 | - r = hashmap_ensure_allocated(&manager->links, NULL); | ||
| 113 | - if (r < 0) | ||
| 114 | - return r; | ||
| 115 | - | ||
| 116 | - r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link); | ||
| 117 | - if (r < 0) | ||
| 118 | - return r; | ||
| 119 | - | ||
| 120 | - r = link_update_flags(link, message, false); | ||
| 121 | - if (r < 0) | ||
| 122 | - return r; | ||
| 123 | - | ||
| 124 | - *ret = TAKE_PTR(link); | ||
| 125 | - | ||
| 126 | - return 0; | ||
| 127 | -} | ||
| 128 | - | ||
| 129 | void link_ntp_settings_clear(Link *link) { | ||
| 130 | link->ntp = strv_free(link->ntp); | ||
| 131 | } | ||
| 132 | @@ -2030,9 +1927,9 @@ static void link_drop_requests(Link *lin | ||
| 133 | request_drop(req); | ||
| 134 | } | ||
| 135 | |||
| 136 | -void link_drop(Link *link) { | ||
| 137 | +Link *link_drop(Link *link) { | ||
| 138 | if (!link) | ||
| 139 | - return; | ||
| 140 | + return NULL; | ||
| 141 | |||
| 142 | assert(link->manager); | ||
| 143 | |||
| 144 | @@ -2057,7 +1954,7 @@ void link_drop(Link *link) { | ||
| 145 | |||
| 146 | /* The following must be called at last. */ | ||
| 147 | assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); | ||
| 148 | - link_unref(link); | ||
| 149 | + return link_unref(link); | ||
| 150 | } | ||
| 151 | |||
| 152 | static int link_joined(Link *link) { | ||
| 153 | @@ -3295,6 +3192,112 @@ ipv4ll_address_fail: | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | + | ||
| 158 | +static Link *link_drop_or_unref(Link *link) { | ||
| 159 | + if (!link) | ||
| 160 | + return NULL; | ||
| 161 | + if (!link->manager) | ||
| 162 | + return link_unref(link); | ||
| 163 | + return link_drop(link); | ||
| 164 | +} | ||
| 165 | + | ||
| 166 | +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_drop_or_unref); | ||
| 167 | + | ||
| 168 | +static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { | ||
| 169 | + _cleanup_(link_drop_or_unrefp) Link *link = NULL; | ||
| 170 | + uint16_t type; | ||
| 171 | + _cleanup_free_ char *ifname = NULL, *kind = NULL; | ||
| 172 | + int r, ifindex; | ||
| 173 | + unsigned short iftype; | ||
| 174 | + | ||
| 175 | + assert(manager); | ||
| 176 | + assert(message); | ||
| 177 | + assert(ret); | ||
| 178 | + | ||
| 179 | + r = sd_netlink_message_get_type(message, &type); | ||
| 180 | + if (r < 0) | ||
| 181 | + return r; | ||
| 182 | + else if (type != RTM_NEWLINK) | ||
| 183 | + return -EINVAL; | ||
| 184 | + | ||
| 185 | + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); | ||
| 186 | + if (r < 0) | ||
| 187 | + return r; | ||
| 188 | + else if (ifindex <= 0) | ||
| 189 | + return -EINVAL; | ||
| 190 | + | ||
| 191 | + r = sd_rtnl_message_link_get_type(message, &iftype); | ||
| 192 | + if (r < 0) | ||
| 193 | + return r; | ||
| 194 | + | ||
| 195 | + r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, &ifname); | ||
| 196 | + if (r < 0) | ||
| 197 | + return r; | ||
| 198 | + | ||
| 199 | + /* check for link kind */ | ||
| 200 | + r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); | ||
| 201 | + if (r >= 0) { | ||
| 202 | + (void) sd_netlink_message_read_string_strdup(message, IFLA_INFO_KIND, &kind); | ||
| 203 | + r = sd_netlink_message_exit_container(message); | ||
| 204 | + if (r < 0) | ||
| 205 | + return r; | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + link = new(Link, 1); | ||
| 209 | + if (!link) | ||
| 210 | + return -ENOMEM; | ||
| 211 | + | ||
| 212 | + *link = (Link) { | ||
| 213 | + .n_ref = 1, | ||
| 214 | + .state = LINK_STATE_PENDING, | ||
| 215 | + .ifindex = ifindex, | ||
| 216 | + .iftype = iftype, | ||
| 217 | + .ifname = TAKE_PTR(ifname), | ||
| 218 | + .kind = TAKE_PTR(kind), | ||
| 219 | + | ||
| 220 | + .n_dns = (unsigned) -1, | ||
| 221 | + .dns_default_route = -1, | ||
| 222 | + .llmnr = _RESOLVE_SUPPORT_INVALID, | ||
| 223 | + .mdns = _RESOLVE_SUPPORT_INVALID, | ||
| 224 | + .dnssec_mode = _DNSSEC_MODE_INVALID, | ||
| 225 | + .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID, | ||
| 226 | + }; | ||
| 227 | + | ||
| 228 | + r = hashmap_ensure_allocated(&manager->links, NULL); | ||
| 229 | + if (r < 0) | ||
| 230 | + return r; | ||
| 231 | + | ||
| 232 | + r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link); | ||
| 233 | + if (r < 0) | ||
| 234 | + return r; | ||
| 235 | + | ||
| 236 | + link->manager = manager; | ||
| 237 | + | ||
| 238 | + r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t*) &link->master_ifindex); | ||
| 239 | + if (r < 0) | ||
| 240 | + log_link_debug_errno(link, r, "New device has no master, continuing without"); | ||
| 241 | + | ||
| 242 | + r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); | ||
| 243 | + if (r < 0) | ||
| 244 | + log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); | ||
| 245 | + | ||
| 246 | + if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) | ||
| 247 | + return -ENOMEM; | ||
| 248 | + | ||
| 249 | + if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) | ||
| 250 | + return -ENOMEM; | ||
| 251 | + | ||
| 252 | + if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) | ||
| 253 | + return -ENOMEM; | ||
| 254 | + | ||
| 255 | + r = link_update_flags(link, message, false); | ||
| 256 | + if (r < 0) | ||
| 257 | + return r; | ||
| 258 | + | ||
| 259 | + *ret = TAKE_PTR(link); | ||
| 260 | + | ||
| 261 | + return 0; | ||
| 262 | +} | ||
| 263 | |||
| 264 | int link_add(Manager *m, sd_netlink_message *message, Link **ret) { | ||
| 265 | _cleanup_(sd_device_unrefp) sd_device *device = NULL; | ||
| 266 | |||
| 267 | --- a/src/network/networkd-link.h 2021-09-02 18:04:16.900542857 +0530 | ||
| 268 | +++ b/src/network/networkd-link.h 2021-09-02 18:18:56.776571563 +0530 | ||
| 269 | @@ -175,7 +175,7 @@ DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_d | ||
| 270 | |||
| 271 | int link_get(Manager *m, int ifindex, Link **ret); | ||
| 272 | int link_add(Manager *manager, sd_netlink_message *message, Link **ret); | ||
| 273 | -void link_drop(Link *link); | ||
| 274 | +Link *link_drop(Link *link); | ||
| 275 | |||
| 276 | int link_down(Link *link, link_netlink_message_handler_t callback); | ||
| 277 | |||
| 278 | |||
diff --git a/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch new file mode 100644 index 0000000000..65bdc611df --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | From 63130eb36dc51e4fd50716c585f98ebe456ca7cf Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||
| 3 | Date: Mon, 17 May 2021 15:40:15 +0900 | ||
| 4 | Subject: [PATCH] network: merge link_drop() and link_detach_from_manager() | ||
| 5 | |||
| 6 | link_detach_from_manager() is only called by link_drop(). It is not | ||
| 7 | necessary to split such tiny function. | ||
| 8 | |||
| 9 | Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/63130eb36dc51e4fd50716c585f98ebe456ca7cf] | ||
| 10 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
| 11 | |||
| 12 | --- | ||
| 13 | src/network/networkd-link.c | 27 ++++++++++++--------------- | ||
| 14 | 1 file changed, 12 insertions(+), 15 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c | ||
| 17 | index 9d30e16b0a..67d01ac44d 100644 | ||
| 18 | --- a/src/network/networkd-link.c | ||
| 19 | +++ b/src/network/networkd-link.c | ||
| 20 | @@ -2019,24 +2019,17 @@ static void link_drop_from_master(Link *link, NetDev *netdev) { | ||
| 21 | link_unref(set_remove(master->slaves, link)); | ||
| 22 | } | ||
| 23 | |||
| 24 | -static void link_detach_from_manager(Link *link) { | ||
| 25 | - if (!link || !link->manager) | ||
| 26 | - return; | ||
| 27 | - | ||
| 28 | - link_unref(set_remove(link->manager->links_requesting_uuid, link)); | ||
| 29 | - link_clean(link); | ||
| 30 | - | ||
| 31 | - /* The following must be called at last. */ | ||
| 32 | - assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); | ||
| 33 | - link_unref(link); | ||
| 34 | -} | ||
| 35 | - | ||
| 36 | void link_drop(Link *link) { | ||
| 37 | - if (!link || link->state == LINK_STATE_LINGER) | ||
| 38 | + if (!link) | ||
| 39 | return; | ||
| 40 | |||
| 41 | + assert(link->manager); | ||
| 42 | + | ||
| 43 | link_set_state(link, LINK_STATE_LINGER); | ||
| 44 | |||
| 45 | + /* Drop all references from other links and manager. Note that async netlink calls may have | ||
| 46 | + * references to the link, and they will be dropped when we receive replies. */ | ||
| 47 | + | ||
| 48 | link_free_carrier_maps(link); | ||
| 49 | |||
| 50 | if (link->network) { | ||
| 51 | @@ -2044,10 +2037,14 @@ void link_drop(Link *link) { | ||
| 52 | link_drop_from_master(link, link->network->bond); | ||
| 53 | } | ||
| 54 | |||
| 55 | - log_link_debug(link, "Link removed"); | ||
| 56 | + link_unref(set_remove(link->manager->links_requesting_uuid, link)); | ||
| 57 | |||
| 58 | (void) unlink(link->state_file); | ||
| 59 | - link_detach_from_manager(link); | ||
| 60 | + link_clean(link); | ||
| 61 | + | ||
| 62 | + /* The following must be called at last. */ | ||
| 63 | + assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); | ||
| 64 | + link_unref(link); | ||
| 65 | } | ||
| 66 | |||
| 67 | static int link_joined(Link *link) { | ||
diff --git a/meta/recipes-core/systemd/systemd_244.5.bb b/meta/recipes-core/systemd/systemd_244.5.bb index 7a7eddcd45..bf33b8d6a1 100644 --- a/meta/recipes-core/systemd/systemd_244.5.bb +++ b/meta/recipes-core/systemd/systemd_244.5.bb | |||
| @@ -22,6 +22,12 @@ SRC_URI += "file://touchscreen.rules \ | |||
| 22 | file://0003-implment-systemd-sysv-install-for-OE.patch \ | 22 | file://0003-implment-systemd-sysv-install-for-OE.patch \ |
| 23 | file://CVE-2021-33910.patch \ | 23 | file://CVE-2021-33910.patch \ |
| 24 | file://CVE-2020-13529.patch \ | 24 | file://CVE-2020-13529.patch \ |
| 25 | file://basic-pass-allocation-info-for-ordered-set-new-and-introd.patch \ | ||
| 26 | file://introduce-ordered_set_clear-free-with-destructor.patch \ | ||
| 27 | file://network-add-skeleton-of-request-queue.patch \ | ||
| 28 | file://network-merge-link_drop-and-link_detach_from_manager.patch \ | ||
| 29 | file://network-also-drop-requests-when-link-enters-linger-state.patch \ | ||
| 30 | file://network-fix-Link-reference-counter-issue.patch \ | ||
| 25 | " | 31 | " |
| 26 | 32 | ||
| 27 | # patches needed by musl | 33 | # patches needed by musl |
