diff --git a/0040-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch b/0040-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch new file mode 100644 index 0000000000000000000000000000000000000000..20d450f113e03eb2e7493cf43ba83ce13f5e4522 --- /dev/null +++ b/0040-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch @@ -0,0 +1,25 @@ +From 13f697b7b1f3837d144ba6f60188bc7dc4d1fbaa Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 13 Oct 2019 00:54:34 +0900 +Subject: [PATCH] systemctl: fix memleak caused by wrong cleanup func + +--- + src/systemctl/systemctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 98a71c4460..738b9af536 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -7977,7 +7977,7 @@ static void help_states(void) { + + static int help_boot_loader_entry(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +- _cleanup_free_ char **l = NULL; ++ _cleanup_strv_free_ char **l = NULL; + sd_bus *bus; + char **i; + int r; +-- +2.23.0 + diff --git a/0041-analyze-fix-minor-memleak.patch b/0041-analyze-fix-minor-memleak.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e62c2c839f64ef1e54c74204d0737a187b4a1f9 --- /dev/null +++ b/0041-analyze-fix-minor-memleak.patch @@ -0,0 +1,25 @@ +From 81610e9609c966a33dcff15a4f3b173aa8f07e4b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 25 Oct 2019 16:05:11 +0200 +Subject: [PATCH] analyze: fix minor memleak + +--- + src/analyze/analyze.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index 1871a4363e..2d541fe701 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -1713,7 +1713,7 @@ static void kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) { + if (syscall[0] == '@') + continue; + +- (void) set_remove(s, syscall); ++ free(set_remove(s, syscall)); + } + } + +-- +2.23.0 + diff --git a/0042-network-add-one-more-section-validty-check.patch b/0042-network-add-one-more-section-validty-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..f2107bb69bcdf261b46d9c14edb30d005a5108eb --- /dev/null +++ b/0042-network-add-one-more-section-validty-check.patch @@ -0,0 +1,28 @@ +From 714a199e481c294b9986b7d5160a89a65d8b375a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 19 Sep 2019 15:20:00 +0900 +Subject: [PATCH] network: add one more section validty check + +Follow-up for 203d4df5732b1fdcf50db498ddeb74a934b21f87. +--- + src/network/networkd-network.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index d1c4cddeb1..a2cd7f4c60 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -300,6 +300,10 @@ int network_verify(Network *network) { + if (section_is_invalid(prefix->section)) + prefix_free(prefix); + ++ LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_route_prefixes) ++ if (section_is_invalid(prefix->section)) ++ prefix_free(prefix); ++ + LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + if (routing_policy_rule_section_verify(rule) < 0) + routing_policy_rule_free(rule); +-- +2.23.0 + diff --git a/0043-network-use-fix-invalid-free-function.patch b/0043-network-use-fix-invalid-free-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..e81147020f39140de521a902503bde788dcd0ca5 --- /dev/null +++ b/0043-network-use-fix-invalid-free-function.patch @@ -0,0 +1,26 @@ +From acb71754e12f98ebd01963869a297ea262494740 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 09:36:39 +0900 +Subject: [PATCH] network: use fix invalid free function + +Fixes #13938. +--- + src/network/networkd-network.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 90d86f35a9..5e82b3c5e0 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -306,7 +306,7 @@ int network_verify(Network *network) { + + LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_route_prefixes) + if (section_is_invalid(prefix->section)) +- prefix_free(prefix); ++ route_prefix_free(prefix); + + LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + if (routing_policy_rule_section_verify(rule) < 0) +-- +2.23.0 + diff --git a/0044-network-fix-memleak.patch b/0044-network-fix-memleak.patch new file mode 100644 index 0000000000000000000000000000000000000000..5aef90cbff2e1b5facb416f2745107f2a0b07d6b --- /dev/null +++ b/0044-network-fix-memleak.patch @@ -0,0 +1,34 @@ +From 9be6ae775fb303deb49ee8e4c5013ce98dc48b93 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 09:39:44 +0900 +Subject: [PATCH] network: fix memleak + +--- + src/network/networkd-network.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 5e82b3c5e0..f6d02fb274 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -586,6 +586,9 @@ static Network *network_free(Network *network) { + while ((prefix = network->static_prefixes)) + prefix_free(prefix); + ++ while ((prefix = network->static_route_prefixes)) ++ route_prefix_free(prefix); ++ + while ((rule = network->rules)) + routing_policy_rule_free(rule); + +@@ -596,6 +599,7 @@ static Network *network_free(Network *network) { + hashmap_free(network->neighbors_by_section); + hashmap_free(network->address_labels_by_section); + hashmap_free(network->prefixes_by_section); ++ hashmap_free(network->route_prefixes_by_section); + hashmap_free(network->rules_by_section); + + if (network->manager) { +-- +2.23.0 + diff --git a/0045-network-Add-support-to-advertie-ipv6-route.patch b/0045-network-Add-support-to-advertie-ipv6-route.patch new file mode 100644 index 0000000000000000000000000000000000000000..4c3e4040503edeb9eb1bd0ad734e7591dbb9b100 --- /dev/null +++ b/0045-network-Add-support-to-advertie-ipv6-route.patch @@ -0,0 +1,711 @@ +From 203d4df5732b1fdcf50db498ddeb74a934b21f87 Mon Sep 17 00:00:00 2001 +From: Susant Sahani +Date: Sat, 14 Sep 2019 16:44:22 +0530 +Subject: [PATCH] network: Add support to advertie ipv6 route + +Implements https://tools.ietf.org/html/rfc4191 + +cat veth99.network +``` +[Match] +Name=veth99 + +[Network] +DHCP=no +IPv6PrefixDelegation=yes +Address=2001:db8:0:1::1/64 + +[IPv6Prefix] +Prefix=2001:db8:0:1::4/64 + +[IPv6RoutePrefix] +Route=2001:db0:fff::/48 + +``` +Wireshark + +``` +Frame 481: 142 bytes on wire (1136 bits), 142 bytes captured (1136 bits) on interface 0 +Ethernet II, Src: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4), Dst: IPv6mcast_01 (33:33:00:00:00:01) +Internet Protocol Version 6, Src: fe80::1c04:f8ff:feb8:2fd4, Dst: ff02::1 +Internet Control Message Protocol v6 + Type: Router Advertisement (134) + Code: 0 + Checksum: 0xec77 [correct] + [Checksum Status: Good] + Cur hop limit: 0 + Flags: 0x00, Prf (Default Router Preference): Medium + Router lifetime (s): 0 + Reachable time (ms): 0 + Retrans timer (ms): 0 + ICMPv6 Option (Source link-layer address : 1e:04:f8:b8:2f:d4) + Type: Source link-layer address (1) + Length: 1 (8 bytes) + Link-layer address: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4) + ICMPv6 Option (MTU : 1500) + Type: MTU (5) + Length: 1 (8 bytes) + Reserved + MTU: 1500 + ICMPv6 Option (Prefix information : 2001:db8:0:1::4/64) + Type: Prefix information (3) + Length: 4 (32 bytes) + Prefix Length: 64 + Flag: 0xc0, On-link flag(L), Autonomous address-configuration flag(A) + Valid Lifetime: 2592000 + Preferred Lifetime: 604800 + Reserved + Prefix: 2001:db8:0:1::4 + ICMPv6 Option (Route Information : Medium 2001:db0:fff::/48) + Type: Route Information (24) + Length: 3 (24 bytes) + Prefix Length: 48 + Flag: 0x00, Route Preference: Medium + ...0 0... = Route Preference: Medium (0) + 000. .000 = Reserved: 0 + Route Lifetime: 604800 + Prefix: 2001:db0:fff:: +``` +--- + man/systemd.network.xml | 33 ++- + src/libsystemd-network/radv-internal.h | 26 +++ + src/libsystemd-network/sd-radv.c | 130 +++++++++++- + src/network/networkd-network-gperf.gperf | 2 + + src/network/networkd-network.c | 1 + + src/network/networkd-network.h | 3 + + src/network/networkd-radv.c | 195 +++++++++++++++++- + src/network/networkd-radv.h | 9 + + src/systemd/sd-radv.h | 10 + + .../fuzz-network-parser/directives.network | 3 + + 10 files changed, 400 insertions(+), 12 deletions(-) + +diff --git a/man/systemd.network.xml b/man/systemd.network.xml +index 155c0868b2..8ecc39ce5e 100644 +--- a/man/systemd.network.xml ++++ b/man/systemd.network.xml +@@ -1886,7 +1886,7 @@ + + + +- ++ + [IPv6Prefix] Section Options + One or more [IPv6Prefix] sections contain the IPv6 + prefixes that are announced via Router Advertisements. See +@@ -1931,6 +1931,37 @@ + + + ++ ++ [IPv6RoutePrefix] Section Options ++ One or more [IPv6RoutePrefix] sections contain the IPv6 ++ prefix routes that are announced via Router Advertisements. See ++ RFC 4191 ++ for further details. ++ ++ ++ ++ ++ Route= ++ ++ The IPv6 route that is to be distributed to hosts. ++ Similarly to configuring static IPv6 routes, the setting is ++ configured as an IPv6 prefix routes and its prefix route length, ++ separated by a/ character. Use multiple ++ [IPv6PrefixRoutes] sections to configure multiple IPv6 ++ prefix routes. ++ ++ ++ ++ LifetimeSec= ++ ++ Lifetime for the route prefix measured in ++ seconds. LifetimeSec= defaults to 604800 seconds (one week). ++ ++ ++ ++ ++ ++ + + [Bridge] Section Options + The [Bridge] section accepts the +diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h +index 7b09c7a66c..fb6617bedd 100644 +--- a/src/libsystemd-network/radv-internal.h ++++ b/src/libsystemd-network/radv-internal.h +@@ -19,6 +19,7 @@ assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC); + #define SD_RADV_MIN_DELAY_BETWEEN_RAS 3 + #define SD_RADV_MAX_RA_DELAY_TIME_USEC (500*USEC_PER_MSEC) + ++#define SD_RADV_OPT_ROUTE_INFORMATION 24 + #define SD_RADV_OPT_RDNSS 25 + #define SD_RADV_OPT_DNSSL 31 + +@@ -58,6 +59,9 @@ struct sd_radv { + unsigned n_prefixes; + LIST_HEAD(sd_radv_prefix, prefixes); + ++ unsigned n_route_prefixes; ++ LIST_HEAD(sd_radv_route_prefix, route_prefixes); ++ + size_t n_rdnss; + struct sd_radv_opt_dns *rdnss; + struct sd_radv_opt_dns *dnssl; +@@ -98,6 +102,28 @@ struct sd_radv_prefix { + usec_t preferred_until; + }; + ++#define radv_route_prefix_opt__contents { \ ++ uint8_t type; \ ++ uint8_t length; \ ++ uint8_t prefixlen; \ ++ uint8_t flags_reserved; \ ++ be32_t lifetime; \ ++ struct in6_addr in6_addr; \ ++} ++ ++struct radv_route_prefix_opt radv_route_prefix_opt__contents; ++ ++struct radv_route_prefix_opt__packed radv_route_prefix_opt__contents _packed_; ++assert_cc(sizeof(struct radv_route_prefix_opt) == sizeof(struct radv_route_prefix_opt__packed)); ++ ++struct sd_radv_route_prefix { ++ unsigned n_ref; ++ ++ struct radv_route_prefix_opt opt; ++ ++ LIST_FIELDS(struct sd_radv_route_prefix, prefix); ++}; ++ + #define log_radv_full(level, error, fmt, ...) log_internal(level, error, PROJECT_FILE, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__) + #define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__) + #define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__) +diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c +index 185b55e1c5..d531f52326 100644 +--- a/src/libsystemd-network/sd-radv.c ++++ b/src/libsystemd-network/sd-radv.c +@@ -116,6 +116,7 @@ static sd_radv *radv_free(sd_radv *ra) { + DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free); + + static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_lifetime) { ++ sd_radv_route_prefix *rt; + sd_radv_prefix *p; + struct sockaddr_in6 dst_addr = { + .sin6_family = AF_INET6, +@@ -136,9 +137,9 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li + .nd_opt_mtu_type = ND_OPT_MTU, + .nd_opt_mtu_len = 1, + }; +- /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, RDNSS ++ /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, N routes, RDNSS + and DNSSL */ +- struct iovec iov[5 + ra->n_prefixes]; ++ struct iovec iov[5 + ra->n_prefixes + ra->n_route_prefixes]; + struct msghdr msg = { + .msg_name = &dst_addr, + .msg_namelen = sizeof(dst_addr), +@@ -190,6 +191,9 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li + iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt)); + } + ++ LIST_FOREACH(prefix, rt, ra->route_prefixes) ++ iov[msg.msg_iovlen++] = IOVEC_MAKE(&rt->opt, sizeof(rt->opt)); ++ + if (ra->rdnss) + iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->rdnss, ra->rdnss->length * 8); + +@@ -606,6 +610,77 @@ _public_ sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, + return cur; + } + ++_public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic) { ++ char time_string_valid[FORMAT_TIMESPAN_MAX]; ++ usec_t time_now, valid, valid_until; ++ _cleanup_free_ char *pretty = NULL; ++ sd_radv_route_prefix *cur; ++ int r; ++ ++ assert_return(ra, -EINVAL); ++ ++ if (!p) ++ return -EINVAL; ++ ++ (void) in_addr_to_string(AF_INET6, ++ (union in_addr_union*) &p->opt.in6_addr, ++ &pretty); ++ ++ LIST_FOREACH(prefix, cur, ra->route_prefixes) { ++ _cleanup_free_ char *addr = NULL; ++ ++ r = in_addr_prefix_intersect(AF_INET6, ++ (union in_addr_union*) &cur->opt.in6_addr, ++ cur->opt.prefixlen, ++ (union in_addr_union*) &p->opt.in6_addr, ++ p->opt.prefixlen); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ continue; ++ ++ if (dynamic && cur->opt.prefixlen == p->opt.prefixlen) ++ goto update; ++ ++ (void) in_addr_to_string(AF_INET6, ++ (union in_addr_union*) &cur->opt.in6_addr, ++ &addr); ++ log_radv("IPv6 route prefix %s/%u already configured, ignoring %s/%u", ++ strempty(addr), cur->opt.prefixlen, ++ strempty(pretty), p->opt.prefixlen); ++ ++ return -EEXIST; ++ } ++ ++ p = sd_radv_route_prefix_ref(p); ++ ++ LIST_APPEND(prefix, ra->route_prefixes, p); ++ ra->n_route_prefixes++; ++ ++ cur = p; ++ if (!dynamic) { ++ log_radv("Added prefix %s/%u", strempty(pretty), p->opt.prefixlen); ++ return 0; ++ } ++ ++ update: ++ r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); ++ if (r < 0) ++ return r; ++ ++ valid = be32toh(p->opt.lifetime) * USEC_PER_SEC; ++ valid_until = usec_add(valid, time_now); ++ if (valid_until == USEC_INFINITY) ++ return -EOVERFLOW; ++ ++ log_radv("%s route prefix %s/%u valid %s", ++ cur? "Updated": "Added", ++ strempty(pretty), p->opt.prefixlen, ++ format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, valid, USEC_PER_SEC)); ++ ++ return 0; ++} ++ + _public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, + const struct in6_addr *dns, size_t n_dns) { + _cleanup_free_ struct sd_radv_opt_dns *opt_rdnss = NULL; +@@ -770,3 +845,54 @@ _public_ int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + + return 0; + } ++ ++_public_ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) { ++ sd_radv_route_prefix *p; ++ ++ assert_return(ret, -EINVAL); ++ ++ p = new(sd_radv_route_prefix, 1); ++ if (!p) ++ return -ENOMEM; ++ ++ *p = (sd_radv_route_prefix) { ++ .n_ref = 1, ++ ++ .opt.type = SD_RADV_OPT_ROUTE_INFORMATION, ++ .opt.length = DIV_ROUND_UP(sizeof(p->opt), 8), ++ .opt.prefixlen = 64, ++ ++ .opt.lifetime = htobe32(604800), ++ }; ++ ++ *ret = p; ++ return 0; ++} ++ ++DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix, sd_radv_route_prefix, mfree); ++ ++_public_ int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, ++ unsigned char prefixlen) { ++ assert_return(p, -EINVAL); ++ assert_return(in6_addr, -EINVAL); ++ ++ if (prefixlen > 128) ++ return -EINVAL; ++ ++ if (prefixlen > 64) ++ /* unusual but allowed, log it */ ++ log_radv("Unusual prefix length %u greater than 64", prefixlen); ++ ++ p->opt.in6_addr = *in6_addr; ++ p->opt.prefixlen = prefixlen; ++ ++ return 0; ++} ++ ++_public_ int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime) { ++ assert_return(p, -EINVAL); ++ ++ p->opt.lifetime = htobe32(valid_lifetime); ++ ++ return 0; ++} +diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf +index d4d108ad25..43163a31ec 100644 +--- a/src/network/networkd-network-gperf.gperf ++++ b/src/network/networkd-network-gperf.gperf +@@ -223,6 +223,8 @@ IPv6Prefix.OnLink, config_parse_prefix_flags, + IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0 + IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0 + IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0 ++IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0 ++IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0 + CAN.BitRate, config_parse_si_size, 0, offsetof(Network, can_bitrate) + CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point) + CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us) +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 70dbd31f50..0608219429 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -458,6 +458,7 @@ int network_load_one(Manager *manager, const char *filename) { + "BridgeVLAN\0" + "IPv6PrefixDelegation\0" + "IPv6Prefix\0" ++ "IPv6RoutePrefix\0" + "CAN\0", + config_item_perf_lookup, network_network_gperf_lookup, + CONFIG_PARSE_WARN, network); +diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h +index bc760744e5..486b8c31a5 100644 +--- a/src/network/networkd-network.h ++++ b/src/network/networkd-network.h +@@ -221,6 +221,7 @@ struct Network { + LIST_HEAD(Neighbor, neighbors); + LIST_HEAD(AddressLabel, address_labels); + LIST_HEAD(Prefix, static_prefixes); ++ LIST_HEAD(Prefix, static_route_prefixes); + LIST_HEAD(RoutingPolicyRule, rules); + + unsigned n_static_addresses; +@@ -230,6 +231,7 @@ struct Network { + unsigned n_neighbors; + unsigned n_address_labels; + unsigned n_static_prefixes; ++ unsigned n_static_route_prefixes; + unsigned n_rules; + + Hashmap *addresses_by_section; +@@ -238,6 +240,7 @@ struct Network { + Hashmap *neighbors_by_section; + Hashmap *address_labels_by_section; + Hashmap *prefixes_by_section; ++ Hashmap *route_prefixes_by_section; + Hashmap *rules_by_section; + + /* All kinds of DNS configuration */ +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 25321aefed..8972c661ae 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -101,16 +101,100 @@ static int prefix_new_static(Network *network, const char *filename, + return 0; + } + ++int route_prefix_new(Prefix **ret) { ++ _cleanup_(prefix_freep) Prefix *prefix = NULL; ++ ++ prefix = new0(Prefix, 1); ++ if (!prefix) ++ return -ENOMEM; ++ ++ if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0) ++ return -ENOMEM; ++ ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++} ++ ++void route_prefix_free(Prefix *prefix) { ++ if (!prefix) ++ return; ++ ++ if (prefix->network) { ++ LIST_REMOVE(prefixes, prefix->network->static_route_prefixes, prefix); ++ assert(prefix->network->n_static_route_prefixes > 0); ++ prefix->network->n_static_route_prefixes--; ++ ++ if (prefix->section) ++ hashmap_remove(prefix->network->route_prefixes_by_section, ++ prefix->section); ++ } ++ ++ network_config_section_free(prefix->section); ++ ++ free(prefix); ++} ++ ++static int route_prefix_new_static(Network *network, const char *filename, ++ unsigned section_line, Prefix **ret) { ++ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; ++ _cleanup_(prefix_freep) Prefix *prefix = NULL; ++ int r; ++ ++ assert(network); ++ assert(ret); ++ assert(!!filename == (section_line > 0)); ++ ++ if (filename) { ++ r = network_config_section_new(filename, section_line, &n); ++ if (r < 0) ++ return r; ++ ++ if (section_line) { ++ prefix = hashmap_get(network->route_prefixes_by_section, n); ++ if (prefix) { ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++ } ++ } ++ } ++ ++ r = route_prefix_new(&prefix); ++ if (r < 0) ++ return r; ++ ++ prefix->network = network; ++ LIST_APPEND(prefixes, network->static_route_prefixes, prefix); ++ network->n_static_route_prefixes++; ++ ++ if (filename) { ++ prefix->section = TAKE_PTR(n); ++ ++ r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops); ++ if (r < 0) ++ return r; ++ ++ r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix); ++ if (r < 0) ++ return r; ++ } ++ ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++} ++ + int config_parse_prefix(const char *unit, +- const char *filename, +- unsigned line, +- const char *section, +- unsigned section_line, +- const char *lvalue, +- int ltype, +- const char *rvalue, +- void *data, +- void *userdata) { ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { + + Network *network = userdata; + _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; +@@ -234,6 +318,90 @@ int config_parse_prefix_lifetime(const char *unit, + return 0; + } + ++int config_parse_route_prefix(const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ ++ Network *network = userdata; ++ _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ uint8_t prefixlen = 64; ++ union in_addr_union in6addr; ++ int r; ++ ++ assert(filename); ++ assert(section); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ r = route_prefix_new_static(network, filename, section_line, &p); ++ if (r < 0) ++ return r; ++ ++ r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Route prefix is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ if (sd_radv_prefix_set_route_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen) < 0) ++ return -EADDRNOTAVAIL; ++ ++ log_syntax(unit, LOG_INFO, filename, line, r, "Found route prefix %s", rvalue); ++ ++ p = NULL; ++ ++ return 0; ++} ++ ++int config_parse_route_prefix_lifetime(const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ Network *network = userdata; ++ _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ usec_t usec; ++ int r; ++ ++ assert(filename); ++ assert(section); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ r = route_prefix_new_static(network, filename, section_line, &p); ++ if (r < 0) ++ return r; ++ ++ r = parse_sec(rvalue, &usec); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Roure lifetime is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ /* a value of 0xffffffff represents infinity */ ++ r = sd_radv_route_prefix_set_lifetime(p->radv_route_prefix, DIV_ROUND_UP(usec, USEC_PER_SEC)); ++ if (r < 0) ++ return r; ++ ++ p = NULL; ++ ++ return 0; ++} ++ + static int radv_get_ip6dns(Network *network, struct in6_addr **dns, + size_t *n_dns) { + _cleanup_free_ struct in6_addr *addresses = NULL; +@@ -438,6 +606,15 @@ int radv_configure(Link *link) { + if (r < 0) + return r; + } ++ ++ LIST_FOREACH(prefixes, p, link->network->static_route_prefixes) { ++ r = sd_radv_add_route_prefix(link->radv, p->radv_route_prefix, false); ++ if (r == -EEXIST) ++ continue; ++ if (r < 0) ++ return r; ++ } ++ + } + + return radv_emit_dns(link); +diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h +index 45be083bfe..2f60b285ae 100644 +--- a/src/network/networkd-radv.h ++++ b/src/network/networkd-radv.h +@@ -26,8 +26,10 @@ struct Prefix { + NetworkConfigSection *section; + + sd_radv_prefix *radv_prefix; ++ sd_radv_route_prefix *radv_route_prefix; + + LIST_FIELDS(Prefix, prefixes); ++ LIST_FIELDS(Prefix, route_prefixes); + }; + + int prefix_new(Prefix **ret); +@@ -35,6 +37,11 @@ void prefix_free(Prefix *prefix); + + DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); + ++int route_prefix_new(Prefix **ret); ++void route_prefix_free(Prefix *prefix); ++ ++DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, route_prefix_free); ++ + int radv_emit_dns(Link *link); + int radv_configure(Link *link); + +@@ -48,3 +55,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); + CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); + CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); + CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); ++CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix); ++CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_lifetime); +diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h +index 93861b9d24..f085231934 100644 +--- a/src/systemd/sd-radv.h ++++ b/src/systemd/sd-radv.h +@@ -37,6 +37,7 @@ _SD_BEGIN_DECLARATIONS; + + typedef struct sd_radv sd_radv; + typedef struct sd_radv_prefix sd_radv_prefix; ++typedef struct sd_radv_route_prefix sd_radv_route_prefix; + + /* Router Advertisement */ + int sd_radv_new(sd_radv **ret); +@@ -59,6 +60,7 @@ int sd_radv_set_managed_information(sd_radv *ra, int managed); + int sd_radv_set_other_information(sd_radv *ra, int other); + int sd_radv_set_preference(sd_radv *ra, unsigned preference); + int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic); ++int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic); + sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, const struct in6_addr *prefix, + unsigned char prefixlen); + int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, +@@ -80,8 +82,16 @@ int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p, + int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + uint32_t preferred_lifetime); + ++int sd_radv_route_prefix_new(sd_radv_route_prefix **ret); ++sd_radv_route_prefix *sd_radv_route_prefix_ref(sd_radv_route_prefix *ra); ++sd_radv_route_prefix *sd_radv_route_prefix_unref(sd_radv_route_prefix *ra); ++ ++int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen); ++int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime); ++ + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref); + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref); ++_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_route_prefix, sd_radv_route_prefix_unref); + + _SD_END_DECLARATIONS; + +diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network +index 848d4bd187..b688d37d08 100644 +--- a/test/fuzz/fuzz-network-parser/directives.network ++++ b/test/fuzz/fuzz-network-parser/directives.network +@@ -174,6 +174,9 @@ OnLink= + PreferredLifetimeSec= + AddressAutoconfiguration= + ValidLifetimeSec= ++[IPv6RoutePrefix] ++Route= ++LifetimeSec= + [BridgeVLAN] + EgressUntagged= + VLAN= +-- +2.23.0 + diff --git a/0046-network-fix-invalid-cleanup-function.patch b/0046-network-fix-invalid-cleanup-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b7d423b6e00198ff2b791884899f61e45fc61f2 --- /dev/null +++ b/0046-network-fix-invalid-cleanup-function.patch @@ -0,0 +1,34 @@ +From e7825b2359d484c606bc1ff8ae3e5ab9aaf980c1 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 10:39:15 +0900 +Subject: [PATCH] network: fix invalid cleanup function + +--- + src/network/networkd-radv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 8972c661ae..4e74756d17 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -330,7 +330,7 @@ int config_parse_route_prefix(const char *unit, + void *userdata) { + + Network *network = userdata; +- _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ _cleanup_(route_prefix_free_or_set_invalidp) Prefix *p = NULL; + uint8_t prefixlen = 64; + union in_addr_union in6addr; + int r; +@@ -372,7 +372,7 @@ int config_parse_route_prefix_lifetime(const char *unit, + void *data, + void *userdata) { + Network *network = userdata; +- _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ _cleanup_(route_prefix_free_or_set_invalidp) Prefix *p = NULL; + usec_t usec; + int r; + +-- +2.23.0 + diff --git a/0047-network-fix-memleak-in-route_prefix_free.patch b/0047-network-fix-memleak-in-route_prefix_free.patch new file mode 100644 index 0000000000000000000000000000000000000000..a63765efbf884e3f1d25e78f0429390191f8f45f --- /dev/null +++ b/0047-network-fix-memleak-in-route_prefix_free.patch @@ -0,0 +1,33 @@ +From 471e126b254dccac66cb2987be3a5f58592d8932 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 10:46:44 +0900 +Subject: [PATCH] network: fix memleak in route_prefix_free() + +--- + src/network/networkd-radv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 8d933f1901..87db34d6cc 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -31,7 +31,7 @@ void prefix_free(Prefix *prefix) { + } + + network_config_section_free(prefix->section); +- prefix->radv_prefix = sd_radv_prefix_unref(prefix->radv_prefix); ++ sd_radv_prefix_unref(prefix->radv_prefix); + + free(prefix); + } +@@ -131,6 +131,7 @@ void route_prefix_free(Prefix *prefix) { + } + + network_config_section_free(prefix->section); ++ sd_radv_route_prefix_unref(prefix->radv_route_prefix); + + free(prefix); + } +-- +2.23.0 + diff --git a/0048-sd-radv-fix-memleak.patch b/0048-sd-radv-fix-memleak.patch new file mode 100644 index 0000000000000000000000000000000000000000..78b131022a5362c82fc18350510bffa0bcfa5d1e --- /dev/null +++ b/0048-sd-radv-fix-memleak.patch @@ -0,0 +1,30 @@ +From 69d7eba1880095f4a9bf9350de777fe7d370c188 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 13:30:00 +0900 +Subject: [PATCH] sd-radv: fix memleak + +--- + src/libsystemd-network/sd-radv.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c +index 5c7f727faa..873a2f40f8 100644 +--- a/src/libsystemd-network/sd-radv.c ++++ b/src/libsystemd-network/sd-radv.c +@@ -99,6 +99,13 @@ static sd_radv *radv_free(sd_radv *ra) { + sd_radv_prefix_unref(p); + } + ++ while (ra->route_prefixes) { ++ sd_radv_route_prefix *p = ra->route_prefixes; ++ ++ LIST_REMOVE(prefix, ra->route_prefixes, p); ++ sd_radv_route_prefix_unref(p); ++ } ++ + free(ra->rdnss); + free(ra->dnssl); + +-- +2.23.0 + diff --git a/0049-sd-bus-invalidate-connection-when-Hello-fails.patch b/0049-sd-bus-invalidate-connection-when-Hello-fails.patch new file mode 100644 index 0000000000000000000000000000000000000000..2b09b2512841356606e02d21a22485e5c165b8d2 --- /dev/null +++ b/0049-sd-bus-invalidate-connection-when-Hello-fails.patch @@ -0,0 +1,66 @@ +From 19fa17c7c4ac228924bd9b7499653a6018abf0b5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 15 Nov 2019 14:23:53 +0100 +Subject: [PATCH] sd-bus: invalidate connection when Hello() fails + +Fixes: #13969 +--- + src/libsystemd/sd-bus/sd-bus.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index ebbfc588ca..058492a83e 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -537,29 +537,41 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e + assert(IN_SET(bus->state, BUS_HELLO, BUS_CLOSING)); + + r = sd_bus_message_get_errno(reply); +- if (r > 0) +- return -r; ++ if (r > 0) { ++ r = -r; ++ goto fail; ++ } + + r = sd_bus_message_read(reply, "s", &s); + if (r < 0) +- return r; ++ goto fail; + +- if (!service_name_is_valid(s) || s[0] != ':') +- return -EBADMSG; ++ if (!service_name_is_valid(s) || s[0] != ':') { ++ r = -EBADMSG; ++ goto fail; ++ } + + r = free_and_strdup(&bus->unique_name, s); + if (r < 0) +- return r; ++ goto fail; + + if (bus->state == BUS_HELLO) { + bus_set_state(bus, BUS_RUNNING); + + r = synthesize_connected_signal(bus); + if (r < 0) +- return r; ++ goto fail; + } + + return 1; ++ ++fail: ++ /* When Hello() failed, let's propagate this in two ways: first we return the error immediately here, ++ * which is the propagated up towards the event loop. Let's also invalidate the connection, so that ++ * if the user then calls back into us again we won't wait any longer. */ ++ ++ bus_set_state(bus, BUS_CLOSING); ++ return r; + } + + static int bus_send_hello(sd_bus *bus) { +-- +2.23.0 + diff --git a/0050-shared-bus-util-Don-t-replace-exsting-strv.patch b/0050-shared-bus-util-Don-t-replace-exsting-strv.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b6ae8ab09970abf4afd784b4dfb37ed7781a885 --- /dev/null +++ b/0050-shared-bus-util-Don-t-replace-exsting-strv.patch @@ -0,0 +1,33 @@ +From 411975ce63b28194b21b964268efaa04b19cbb37 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Tue, 10 Dec 2019 01:58:01 -0800 +Subject: [PATCH] shared/bus-util: Don't replace exsting strv + +Change the behavior of string arrays in a bus property map. Previously, +passing the same strv pointer to more than one map entry would result in +the old strv being freed and overwritten. With this change, an existing +strv pointer is appended to. + +This is important if we want to create one strv comprised of multiple +dependencies. This makes it so callers don't have to create one strv per +dependency and subsequently merge them into one strv. +--- + src/shared/bus-util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index aea46d3119..10c05eba18 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -1127,7 +1127,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigne + if (r < 0) + return r; + +- return strv_free_and_replace(*p, l); ++ return strv_extend_strv(p, l, false); + } + + case SD_BUS_TYPE_BOOLEAN: { +-- +2.23.0 + diff --git a/0051-systemctl-Add-with-dependencies-flag.patch b/0051-systemctl-Add-with-dependencies-flag.patch new file mode 100644 index 0000000000000000000000000000000000000000..8fc4800efa828a9c75723260d956db7264c56f02 --- /dev/null +++ b/0051-systemctl-Add-with-dependencies-flag.patch @@ -0,0 +1,330 @@ +From e9c387c8293c57d1c773fc80d23239350eb3b370 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Sun, 8 Dec 2019 15:23:27 -0800 +Subject: [PATCH] systemctl: Add --with-dependencies flag + +Will print a unit and all of its dependencies. Works with cat, status, +list-units, and list-unit-files. This flag can also be used in conjunction +with --reverse, --before, and --after. + +We also vastly simplify the list_dependencies_get_dependencies logic. +Instead of using 5 strvs and merging them into one, use one strv and +have the bus append all the map values to it. + +Fixes #9273 +--- + src/systemctl/systemctl.c | 227 +++++++++++++++++++++++++------------- + 1 file changed, 148 insertions(+), 79 deletions(-) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 6a0e59a4d7..0873045173 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -117,6 +117,7 @@ static bool arg_dry_run = false; + static bool arg_quiet = false; + static bool arg_full = false; + static bool arg_recursive = false; ++static bool arg_with_dependencies = false; + static bool arg_show_transaction = false; + static int arg_force = 0; + static bool arg_ask_password = false; +@@ -799,6 +800,107 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r + return c; + } + ++static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***ret) { ++ _cleanup_strv_free_ char **deps = NULL; ++ ++ static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = { ++ [DEPENDENCY_FORWARD] = { ++ { "Requires", "as", NULL, 0 }, ++ { "Requisite", "as", NULL, 0 }, ++ { "Wants", "as", NULL, 0 }, ++ { "ConsistsOf", "as", NULL, 0 }, ++ { "BindsTo", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_REVERSE] = { ++ { "RequiredBy", "as", NULL, 0 }, ++ { "RequisiteOf", "as", NULL, 0 }, ++ { "WantedBy", "as", NULL, 0 }, ++ { "PartOf", "as", NULL, 0 }, ++ { "BoundBy", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_AFTER] = { ++ { "After", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_BEFORE] = { ++ { "Before", "as", NULL, 0 }, ++ {} ++ }, ++ }; ++ ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_free_ char *dbus_path = NULL; ++ int r; ++ ++ assert(bus); ++ assert(name); ++ assert(ret); ++ ++ dbus_path = unit_dbus_path_from_name(name); ++ if (!dbus_path) ++ return log_oom(); ++ ++ r = bus_map_all_properties(bus, ++ "org.freedesktop.systemd1", ++ dbus_path, ++ map[arg_dependency], ++ BUS_MAP_STRDUP, ++ &error, ++ NULL, ++ &deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); ++ ++ *ret = TAKE_PTR(deps); ++ ++ return 0; ++} ++ ++static int append_unit_dependencies(sd_bus *bus, char **names, char ***ret) { ++ _cleanup_strv_free_ char **with_deps = NULL; ++ char **name; ++ ++ assert(bus); ++ assert(ret); ++ ++ STRV_FOREACH(name, names) { ++ _cleanup_strv_free_ char **deps = NULL; ++ ++ if (strv_extend(&with_deps, *name) < 0) ++ return log_oom(); ++ ++ (void) list_dependencies_get_dependencies(bus, *name, &deps); ++ ++ if (strv_extend_strv(&with_deps, deps, true) < 0) ++ return log_oom(); ++ } ++ ++ *ret = TAKE_PTR(with_deps); ++ ++ return 0; ++} ++ ++static int maybe_extend_with_unit_dependencies(sd_bus *bus, char ***list) { ++ assert(bus); ++ assert(list); ++ ++ if (arg_with_dependencies) { ++ int r; ++ _cleanup_strv_free_ char **list_with_deps = NULL; ++ ++ r = append_unit_dependencies(bus, *list, &list_with_deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to append unit dependencies: %m"); ++ ++ strv_free(*list); ++ *list = TAKE_PTR(list_with_deps); ++ } ++ ++ return 0; ++} ++ + static int list_units(int argc, char *argv[], void *userdata) { + _cleanup_free_ UnitInfo *unit_infos = NULL; + _cleanup_(message_set_freep) Set *replies = NULL; +@@ -812,9 +914,21 @@ static int list_units(int argc, char *argv[], void *userdata) { + + (void) pager_open(arg_pager_flags); + +- r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); +- if (r < 0) +- return r; ++ if (arg_with_dependencies) { ++ _cleanup_strv_free_ char **names = NULL; ++ ++ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names); ++ if (r < 0) ++ return r; ++ ++ r = get_unit_list_recursive(bus, names, &unit_infos, &replies, &machines); ++ if (r < 0) ++ return r; ++ } else { ++ r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); ++ if (r < 0) ++ return r; ++ } + + typesafe_qsort(unit_infos, r, compare_unit_info); + return output_units_list(unit_infos, r); +@@ -1571,9 +1685,21 @@ static int list_unit_files(int argc, char *argv[], void *userdata) { + if (r < 0) + return bus_log_create_error(r); + +- r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); +- if (r < 0) +- return bus_log_create_error(r); ++ if (arg_with_dependencies) { ++ _cleanup_strv_free_ char **names_with_deps = NULL; ++ ++ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names_with_deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to append unit dependencies: %m"); ++ ++ r = sd_bus_message_append_strv(m, names_with_deps); ++ if (r < 0) ++ return bus_log_create_error(r); ++ } else { ++ r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); ++ if (r < 0) ++ return bus_log_create_error(r); ++ } + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) { +@@ -1677,79 +1803,6 @@ static int list_dependencies_print(const char *name, int level, unsigned branche + return 0; + } + +-static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) { +- struct DependencyStatusInfo { +- char **dep[5]; +- } info = {}; +- +- static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = { +- [DEPENDENCY_FORWARD] = { +- { "Requires", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- { "Requisite", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, +- { "Wants", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, +- { "ConsistsOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, +- { "BindsTo", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, +- {} +- }, +- [DEPENDENCY_REVERSE] = { +- { "RequiredBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- { "RequisiteOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, +- { "WantedBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, +- { "PartOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, +- { "BoundBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, +- {} +- }, +- [DEPENDENCY_AFTER] = { +- { "After", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- {} +- }, +- [DEPENDENCY_BEFORE] = { +- { "Before", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- {} +- }, +- }; +- +- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +- _cleanup_strv_free_ char **ret = NULL; +- _cleanup_free_ char *dbus_path = NULL; +- int i, r; +- +- assert(bus); +- assert(name); +- assert(deps); +- +- dbus_path = unit_dbus_path_from_name(name); +- if (!dbus_path) +- return log_oom(); +- +- r = bus_map_all_properties(bus, +- "org.freedesktop.systemd1", +- dbus_path, +- map[arg_dependency], +- BUS_MAP_STRDUP, +- &error, +- NULL, +- &info); +- if (r < 0) +- return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); +- +- if (IN_SET(arg_dependency, DEPENDENCY_AFTER, DEPENDENCY_BEFORE)) { +- *deps = info.dep[0]; +- return 0; +- } +- +- for (i = 0; i < 5; i++) { +- r = strv_extend_strv(&ret, info.dep[i], true); +- if (r < 0) +- return log_oom(); +- info.dep[i] = strv_free(info.dep[i]); +- } +- +- *deps = TAKE_PTR(ret); +- +- return 0; +-} +- + static int list_dependencies_compare(char * const *a, char * const *b) { + if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET) + return 1; +@@ -5909,6 +5962,10 @@ static int show(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + ++ r = maybe_extend_with_unit_dependencies(bus, &names); ++ if (r < 0) ++ return r; ++ + STRV_FOREACH(name, names) { + _cleanup_free_ char *path; + +@@ -5959,6 +6016,10 @@ static int cat(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + ++ r = maybe_extend_with_unit_dependencies(bus, &names); ++ if (r < 0) ++ return r; ++ + (void) pager_open(arg_pager_flags); + + STRV_FOREACH(name, names) { +@@ -7945,6 +8006,9 @@ static int systemctl_help(void) { + " -l --full Don't ellipsize unit names on output\n" + " -r --recursive Show unit list of host and local containers\n" + " --reverse Show reverse dependencies with 'list-dependencies'\n" ++ " --with-dependencies\n" ++ " Show unit dependencies with 'status', 'cat',\n" ++ " 'list-units', and 'list-unit-files'.\n" + " --job-mode=MODE Specify how to deal with already queued jobs, when\n" + " queueing a new job\n" + " -T --show-transaction\n" +@@ -8235,6 +8298,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + ARG_BOOT_LOADER_ENTRY, + ARG_NOW, + ARG_MESSAGE, ++ ARG_WITH_DEPENDENCIES, + ARG_WAIT, + ARG_WHAT, + }; +@@ -8281,6 +8345,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + { "plain", no_argument, NULL, ARG_PLAIN }, + { "state", required_argument, NULL, ARG_STATE }, + { "recursive", no_argument, NULL, 'r' }, ++ { "with-dependencies", no_argument, NULL, ARG_WITH_DEPENDENCIES }, + { "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, + { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP }, + { "boot-loader-menu", required_argument, NULL, ARG_BOOT_LOADER_MENU }, +@@ -8641,6 +8706,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + arg_show_transaction = true; + break; + ++ case ARG_WITH_DEPENDENCIES: ++ arg_with_dependencies = true; ++ break; ++ + case ARG_WHAT: { + const char *p; + +-- +2.23.0 + diff --git a/0052-man-Document-systemctl-with-dependencies-switch.patch b/0052-man-Document-systemctl-with-dependencies-switch.patch new file mode 100644 index 0000000000000000000000000000000000000000..46d3314bff9ca1fd62ed3ca16655d4797b4a2abd --- /dev/null +++ b/0052-man-Document-systemctl-with-dependencies-switch.patch @@ -0,0 +1,39 @@ +From a602a0b44b9eb9af0027d054dd24e405a658e375 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Mon, 9 Dec 2019 01:40:47 -0800 +Subject: [PATCH] man: Document systemctl --with-dependencies switch + +--- + man/systemctl.xml | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index 3d86f7dffa..5828477e8d 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -1592,6 +1592,22 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + + + ++ ++ ++ ++ ++ When used with status, ++ cat, list-units, and ++ list-unit-files, those commands print all ++ specified units and the dependencies of those units. ++ ++ Options , ++ , ++ may be used to change what types of dependencies ++ are shown. ++ ++ ++ + + + +-- +2.23.0 + diff --git a/0053-core-expose-swap-priority-value-via-dbus-only-if-it-.patch b/0053-core-expose-swap-priority-value-via-dbus-only-if-it-.patch new file mode 100644 index 0000000000000000000000000000000000000000..4baab93b7a3e5d7a1e49a9c36446e089dd913d61 --- /dev/null +++ b/0053-core-expose-swap-priority-value-via-dbus-only-if-it-.patch @@ -0,0 +1,42 @@ +From 6d9e0ca400133aeffa4a53c707db43b3e6c98c7b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:01:14 +0100 +Subject: [PATCH] core: expose swap priority value via dbus only if it is set + +--- + src/core/dbus-swap.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c +index 353fa20132..57c8c42091 100644 +--- a/src/core/dbus-swap.c ++++ b/src/core/dbus-swap.c +@@ -12,16 +12,23 @@ + #include "unit.h" + + static int swap_get_priority(Swap *s) { +- if (s->from_proc_swaps) ++ assert(s); ++ ++ if (s->from_proc_swaps && s->parameters_proc_swaps.priority_set) + return s->parameters_proc_swaps.priority; +- if (s->from_fragment) ++ ++ if (s->from_fragment && s->parameters_fragment.priority_set) + return s->parameters_fragment.priority; ++ + return -1; + } + + static const char *swap_get_options(Swap *s) { ++ assert(s); ++ + if (s->from_fragment) + return s->parameters_fragment.options; ++ + return NULL; + } + +-- +2.23.0 + diff --git a/0054-tree-wide-we-forgot-to-destroy-some-bus-errors.patch b/0054-tree-wide-we-forgot-to-destroy-some-bus-errors.patch new file mode 100644 index 0000000000000000000000000000000000000000..92beba286c2888cdb85aa69f9d46ac040f0c3d6b --- /dev/null +++ b/0054-tree-wide-we-forgot-to-destroy-some-bus-errors.patch @@ -0,0 +1,39 @@ +From 7e284b054ec599012f0dad6a745f6b52eba87853 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 17 Jan 2020 15:37:56 +0100 +Subject: [PATCH] tree-wide: we forgot to destroy some bus errors + +--- + src/libsystemd/sd-bus/test-bus-server.c | 2 +- + src/locale/localed.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c +index e38bcdcc76..82eb35e5b1 100644 +--- a/src/libsystemd/sd-bus/test-bus-server.c ++++ b/src/libsystemd/sd-bus/test-bus-server.c +@@ -108,7 +108,7 @@ fail: + static int client(struct context *c) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; +- sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert_se(sd_bus_new(&bus) >= 0); +diff --git a/src/locale/localed.c b/src/locale/localed.c +index baf0bd102b..2031cd25ce 100644 +--- a/src/locale/localed.c ++++ b/src/locale/localed.c +@@ -33,7 +33,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) { + _cleanup_free_ char **l_unset = NULL; + _cleanup_strv_free_ char **l_set = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; +- sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + size_t c_set, c_unset; + LocaleVariable p; + int r; +-- +2.23.0 + diff --git a/0055-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch b/0055-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch new file mode 100644 index 0000000000000000000000000000000000000000..d937f86641662498eb05170366b7b73752134b15 --- /dev/null +++ b/0055-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch @@ -0,0 +1,25 @@ +From 58abbbcc6bcedc4eebd1f5c7733cd41518e1f2e3 Mon Sep 17 00:00:00 2001 +From: sangelovic +Date: Mon, 27 Jan 2020 21:40:37 +0100 +Subject: [PATCH] sd-bus: fix introspection bug in signal parameter names + +--- + src/libsystemd/sd-bus/bus-introspect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c +index beab80687d..e8934489b5 100644 +--- a/src/libsystemd/sd-bus/bus-introspect.c ++++ b/src/libsystemd/sd-bus/bus-introspect.c +@@ -160,7 +160,7 @@ int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) { + case _SD_BUS_VTABLE_SIGNAL: + fprintf(i->f, " \n", v->x.signal.member); + if (bus_vtable_has_names(vtable)) +- names = strempty(v->x.method.names); ++ names = strempty(v->x.signal.names); + introspect_write_arguments(i, strempty(v->x.signal.signature), &names, NULL); + introspect_write_flags(i, v->type, v->flags); + fputs(" \n", i->f); +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index f2e943523c558f6eb3ac9e975c39acbfce5641fe..c9cccb31ebd104b51ba4f4889a45748a747e21dc 100644 --- a/systemd.spec +++ b/systemd.spec @@ -87,6 +87,22 @@ Patch0037: revert-shared-unit-file-add-a-function-to-validate-u.patch Patch0038: systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch Patch0039: seccomp-more-comprehensive-protection-against-libsec.patch +Patch0040: 0040-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch +Patch0041: 0041-analyze-fix-minor-memleak.patch +Patch0042: 0042-network-add-one-more-section-validty-check.patch +Patch0043: 0043-network-use-fix-invalid-free-function.patch +Patch0044: 0044-network-fix-memleak.patch +Patch0045: 0045-network-Add-support-to-advertie-ipv6-route.patch +Patch0046: 0046-network-fix-invalid-cleanup-function.patch +Patch0047: 0047-network-fix-memleak-in-route_prefix_free.patch +Patch0048: 0048-sd-radv-fix-memleak.patch +Patch0049: 0049-sd-bus-invalidate-connection-when-Hello-fails.patch +Patch0050: 0050-shared-bus-util-Don-t-replace-exsting-strv.patch +Patch0051: 0051-systemctl-Add-with-dependencies-flag.patch +Patch0052: 0052-man-Document-systemctl-with-dependencies-switch.patch +Patch0053: 0053-core-expose-swap-priority-value-via-dbus-only-if-it-.patch +Patch0054: 0054-tree-wide-we-forgot-to-destroy-some-bus-errors.patch +Patch0055: 0055-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch Patch9003: 1602-activation-service-must-be-restarted-when-reactivated.patch