From 18e97c565df75cbf250c07223cd4deadd265e24a Mon Sep 17 00:00:00 2001 From: Tad Date: Tue, 19 Apr 2022 23:28:05 -0400 Subject: [PATCH] 19.1: missed hosts work Signed-off-by: Tad --- .../android_bionic/0003-Hosts_Cache.patch | 646 ++++++++++++++++++ .../android_bionic/0003-Hosts_Wildcards.patch | 72 ++ Scripts/LineageOS-19.1/Patch.sh | 2 + 3 files changed, 720 insertions(+) create mode 100644 Patches/LineageOS-19.1/android_bionic/0003-Hosts_Cache.patch create mode 100644 Patches/LineageOS-19.1/android_bionic/0003-Hosts_Wildcards.patch diff --git a/Patches/LineageOS-19.1/android_bionic/0003-Hosts_Cache.patch b/Patches/LineageOS-19.1/android_bionic/0003-Hosts_Cache.patch new file mode 100644 index 00000000..a048b8e1 --- /dev/null +++ b/Patches/LineageOS-19.1/android_bionic/0003-Hosts_Cache.patch @@ -0,0 +1,646 @@ +From d7d848b5d0b398e7a85d4d7ca112bbf3198ff6a5 Mon Sep 17 00:00:00 2001 +From: Tom Marshall +Date: Fri, 17 Jun 2016 16:38:12 -0700 +Subject: [PATCH] bionic: Sort and cache hosts file data for fast lookup + +The hosts file is normally searched linearly. This is very slow when +the file is large. To mitigate this, read the hosts file and sort the +entries in an in-memory cache. When an address is requested via +gethostbyname or getaddrinfo, binary search the cache. + +In case where the cache is not available, return a suitable error code +and fall back to the existing lookup code. + +This has been written to behave as much like the existing lookup code as +possible. But note bionic and glibc differ in behavior for some corner +cases. Choose the most standard compliant behavior for these where +possible. Otherwise choose the behavior that seems most reasonable. + +RM-290 + +Change-Id: I3b322883cbc48b0d76a0ce9d149b59faaac1dc58 +(cherry picked from commit ed4c3a6bd449a4ed70645071a440ae146f194116) +--- + libc/dns/net/getaddrinfo.c | 10 + + libc/dns/net/hosts_cache.c | 524 +++++++++++++++++++++++++++++++++++++ + libc/dns/net/hosts_cache.h | 23 ++ + libc/dns/net/sethostent.c | 7 + + 4 files changed, 564 insertions(+) + create mode 100644 libc/dns/net/hosts_cache.c + create mode 100644 libc/dns/net/hosts_cache.h + +diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c +index d0c11d2b0..cc94b21e2 100644 +--- a/libc/dns/net/getaddrinfo.c ++++ b/libc/dns/net/getaddrinfo.c +@@ -109,6 +109,8 @@ + #include "nsswitch.h" + #include "private/bionic_defs.h" + ++#include "hosts_cache.h" ++ + typedef union sockaddr_union { + struct sockaddr generic; + struct sockaddr_in in; +@@ -2125,6 +2127,14 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap) + name = va_arg(ap, char *); + pai = va_arg(ap, struct addrinfo *); + ++ memset(&sentinel, 0, sizeof(sentinel)); ++ cur = &sentinel; ++ int gai_error = hc_getaddrinfo(name, NULL, pai, &cur); ++ if (gai_error != EAI_SYSTEM) { ++ *((struct addrinfo **)rv) = sentinel.ai_next; ++ return (gai_error == 0 ? NS_SUCCESS : NS_NOTFOUND); ++ } ++ + // fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; +diff --git a/libc/dns/net/hosts_cache.c b/libc/dns/net/hosts_cache.c +new file mode 100644 +index 000000000..deafb78b7 +--- /dev/null ++++ b/libc/dns/net/hosts_cache.c +@@ -0,0 +1,524 @@ ++/* ++ * Copyright (C) 2016 The CyanogenMod Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "hostent.h" ++#include "resolv_private.h" ++ ++#define MAX_ADDRLEN (INET6_ADDRSTRLEN - (1 + 5)) ++#define MAX_HOSTLEN MAXHOSTNAMELEN ++ ++#define ESTIMATED_LINELEN 32 ++#define HCFILE_ALLOC_SIZE 256 ++ ++/* From sethostent.c */ ++#define ALIGNBYTES (sizeof(uintptr_t) - 1) ++#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES) ++ ++/* ++ * Host cache entry for hcfile.c_data. ++ * Offsets are into hcfile.h_data. ++ * Strings are *not* terminated by NULL, but by whitespace (isspace) or '#'. ++ * Use hstr* functions with these. ++ */ ++struct hcent ++{ ++ uint32_t addr; ++ uint32_t name; ++}; ++ ++/* ++ * Overall host cache file state. ++ */ ++struct hcfile ++{ ++ int h_fd; ++ struct stat h_st; ++ char *h_data; ++ ++ uint32_t c_alloc; ++ uint32_t c_len; ++ struct hcent *c_data; ++}; ++static struct hcfile hcfile; ++static pthread_mutex_t hclock = PTHREAD_MUTEX_INITIALIZER; ++ ++static size_t hstrlen(const char *s) ++{ ++ const char *p = s; ++ while (*p && *p != '#' && !isspace(*p)) ++ ++p; ++ return p - s; ++} ++ ++static int hstrcmp(const char *a, const char *b) ++{ ++ size_t alen = hstrlen(a); ++ size_t blen = hstrlen(b); ++ int res = strncmp(a, b, MIN(alen, blen)); ++ if (res == 0) ++ res = alen - blen; ++ return res; ++} ++ ++static char *hstrcpy(char *dest, const char *src) ++{ ++ size_t len = hstrlen(src); ++ memcpy(dest, src, len); ++ dest[len] = '\0'; ++ return dest; ++} ++ ++static char *hstrdup(const char *s) ++{ ++ size_t len = hstrlen(s); ++ char *dest = (char *)malloc(len + 1); ++ if (!dest) ++ return NULL; ++ memcpy(dest, s, len); ++ dest[len] = '\0'; ++ return dest; ++} ++ ++static int cmp_hcent_name(const void *a, const void *b) ++{ ++ struct hcent *ea = (struct hcent *)a; ++ const char *na = hcfile.h_data + ea->name; ++ struct hcent *eb = (struct hcent *)b; ++ const char *nb = hcfile.h_data + eb->name; ++ ++ return hstrcmp(na, nb); ++} ++ ++static struct hcent *_hcfindname(const char *name) ++{ ++ size_t first, last, mid; ++ struct hcent *cur = NULL; ++ int cmp; ++ ++ if (hcfile.c_len == 0) ++ return NULL; ++ ++ first = 0; ++ last = hcfile.c_len - 1; ++ mid = (first + last) / 2; ++ while (first <= last) { ++ cur = hcfile.c_data + mid; ++ cmp = hstrcmp(hcfile.h_data + cur->name, name); ++ if (cmp == 0) ++ goto found; ++ if (cmp < 0) ++ first = mid + 1; ++ else { ++ if (mid > 0) ++ last = mid - 1; ++ else ++ return NULL; ++ } ++ mid = (first + last) / 2; ++ } ++ return NULL; ++ ++found: ++ while (cur > hcfile.c_data) { ++ struct hcent *prev = cur - 1; ++ cmp = cmp_hcent_name(cur, prev); ++ if (cmp) ++ break; ++ cur = prev; ++ } ++ ++ return cur; ++} ++ ++/* ++ * Find next name on line, if any. ++ * ++ * Assumes that line is terminated by LF. ++ */ ++static const char *_hcnextname(const char *name) ++{ ++ while (!isspace(*name)) { ++ if (*name == '#') ++ return NULL; ++ ++name; ++ } ++ while (isspace(*name)) { ++ if (*name == '\n') ++ return NULL; ++ ++name; ++ } ++ if (*name == '#') ++ return NULL; ++ return name; ++} ++ ++static int _hcfilemmap(void) ++{ ++ struct stat st; ++ int h_fd; ++ char *h_addr; ++ const char *p, *pend; ++ uint32_t c_alloc; ++ ++ h_fd = open(_PATH_HOSTS, O_RDONLY); ++ if (h_fd < 0) ++ return -1; ++ if (flock(h_fd, LOCK_EX) != 0) { ++ close(h_fd); ++ return -1; ++ } ++ ++ if (hcfile.h_data) { ++ memset(&st, 0, sizeof(st)); ++ if (fstat(h_fd, &st) == 0) { ++ if (st.st_size == hcfile.h_st.st_size && ++ st.st_mtime == hcfile.h_st.st_mtime) { ++ flock(h_fd, LOCK_UN); ++ close(h_fd); ++ return 0; ++ } ++ } ++ free(hcfile.c_data); ++ munmap(hcfile.h_data, hcfile.h_st.st_size); ++ close(hcfile.h_fd); ++ memset(&hcfile, 0, sizeof(struct hcfile)); ++ } ++ ++ if (fstat(h_fd, &st) != 0) { ++ flock(h_fd, LOCK_UN); ++ close(h_fd); ++ return -1; ++ } ++ h_addr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, h_fd, 0); ++ if (h_addr == MAP_FAILED) { ++ flock(h_fd, LOCK_UN); ++ close(h_fd); ++ return -1; ++ } ++ ++ hcfile.h_fd = h_fd; ++ hcfile.h_st = st; ++ hcfile.h_data = h_addr; ++ ++ c_alloc = 0; ++ /* ++ * Do an initial allocation if the file is "large". Estimate ++ * 32 bytes per line and define "large" as more than half of ++ * the alloc growth size (256 entries). ++ */ ++ if (st.st_size >= ESTIMATED_LINELEN * HCFILE_ALLOC_SIZE / 2) { ++ c_alloc = st.st_size / ESTIMATED_LINELEN; ++ hcfile.c_data = malloc(c_alloc * sizeof(struct hcent)); ++ if (!hcfile.c_data) { ++ goto oom; ++ } ++ } ++ ++ p = (const char *)h_addr; ++ pend = p + st.st_size; ++ while (p < pend) { ++ const char *eol, *addr, *name; ++ size_t len; ++ addr = p; ++ eol = memchr(p, '\n', pend - p); ++ if (!eol) ++ break; ++ p = eol + 1; ++ if (*addr == '#' || *addr == '\n') ++ continue; ++ len = hstrlen(addr); ++ if (len > MAX_ADDRLEN) ++ continue; ++ name = addr + len; ++ while (name < eol && isspace(*name)) ++ ++name; ++ while (name < eol) { ++ len = hstrlen(name); ++ if (len == 0) ++ break; ++ if (len < MAX_HOSTLEN) { ++ struct hcent *ent; ++ if (c_alloc <= hcfile.c_len) { ++ struct hcent *c_data; ++ c_alloc += HCFILE_ALLOC_SIZE; ++ c_data = realloc(hcfile.c_data, c_alloc * sizeof(struct hcent)); ++ if (!c_data) { ++ goto oom; ++ } ++ hcfile.c_data = c_data; ++ } ++ ent = hcfile.c_data + hcfile.c_len; ++ ent->addr = addr - h_addr; ++ ent->name = name - h_addr; ++ ++hcfile.c_len; ++ } ++ name += len; ++ while (name < eol && isspace(*name)) ++ ++name; ++ } ++ } ++ ++ qsort(hcfile.c_data, hcfile.c_len, ++ sizeof(struct hcent), cmp_hcent_name); ++ ++ flock(h_fd, LOCK_UN); ++ ++ return 0; ++ ++oom: ++ free(hcfile.c_data); ++ munmap(hcfile.h_data, hcfile.h_st.st_size); ++ flock(hcfile.h_fd, LOCK_UN); ++ close(hcfile.h_fd); ++ memset(&hcfile, 0, sizeof(struct hcfile)); ++ return -1; ++} ++ ++/* ++ * Caching version of getaddrinfo. ++ * ++ * If we find the requested host name in the cache, use getaddrinfo to ++ * populate the result for each address we find. ++ * ++ * Note glibc and bionic differ in the handling of ai_canonname. POSIX ++ * says that ai_canonname is only populated in the first result entry. ++ * glibc does this. bionic populates ai_canonname in all result entries. ++ * We choose the POSIX/glibc way here. ++ */ ++int hc_getaddrinfo(const char *host, const char *service, ++ const struct addrinfo *hints, ++ struct addrinfo **result) ++{ ++ int ret = 0; ++ struct hcent *ent, *cur; ++ struct addrinfo *ai; ++ struct addrinfo rhints; ++ struct addrinfo *last; ++ int canonname = 0; ++ int cmp; ++ ++ if (getenv("ANDROID_HOSTS_CACHE_DISABLE") != NULL) ++ return EAI_SYSTEM; ++ ++ /* Avoid needless work and recursion */ ++ if (hints && (hints->ai_flags & AI_NUMERICHOST)) ++ return EAI_SYSTEM; ++ if (!host) ++ return EAI_SYSTEM; ++ ++ pthread_mutex_lock(&hclock); ++ ++ if (_hcfilemmap() != 0) { ++ ret = EAI_SYSTEM; ++ goto out; ++ } ++ ent = _hcfindname(host); ++ if (!ent) { ++ ret = EAI_NONAME; ++ goto out; ++ } ++ ++ if (hints) { ++ canonname = (hints->ai_flags & AI_CANONNAME); ++ memcpy(&rhints, hints, sizeof(rhints)); ++ rhints.ai_flags &= ~AI_CANONNAME; ++ } ++ else { ++ memset(&rhints, 0, sizeof(rhints)); ++ } ++ rhints.ai_flags |= AI_NUMERICHOST; ++ ++ last = NULL; ++ cur = ent; ++ do { ++ char addrstr[MAX_ADDRLEN]; ++ struct addrinfo *res; ++ ++ hstrcpy(addrstr, hcfile.h_data + cur->addr); ++ ++ if (getaddrinfo(addrstr, service, &rhints, &res) == 0) { ++ if (!last) ++ (*result)->ai_next = res; ++ else ++ last->ai_next = res; ++ last = res; ++ while (last->ai_next) ++ last = last->ai_next; ++ } ++ ++ if(cur + 1 >= hcfile.c_data + hcfile.c_len) ++ break; ++ cmp = cmp_hcent_name(cur, cur + 1); ++ cur = cur + 1; ++ } ++ while (!cmp); ++ ++ if (last == NULL) { ++ /* This check is equivalent to (*result)->ai_next == NULL */ ++ ret = EAI_NODATA; ++ goto out; ++ } ++ ++ if (canonname) { ++ ai = (*result)->ai_next; ++ free(ai->ai_canonname); ++ ai->ai_canonname = hstrdup(hcfile.h_data + ent->name); ++ } ++ ++out: ++ pthread_mutex_unlock(&hclock); ++ return ret; ++} ++ ++/* ++ * Caching version of gethtbyname. ++ * ++ * Note glibc and bionic differ in the handling of aliases. glibc returns ++ * all aliases for all entries, regardless of whether they match h_addrtype. ++ * bionic returns only the aliases for the first hosts entry. We return all ++ * aliases for all IPv4 entries. ++ * ++ * Additionally, if an alias is IPv6 and the primary name for an alias also ++ * has an IPv4 entry, glibc will return the IPv4 address(es), but bionic ++ * will not. Neither do we. ++ */ ++int hc_gethtbyname(const char *host, int af, struct getnamaddr *info) ++{ ++ int ret = NETDB_SUCCESS; ++ struct hcent *ent, *cur; ++ int cmp; ++ size_t addrlen; ++ unsigned int naliases = 0; ++ char *aliases[MAXALIASES]; ++ unsigned int naddrs = 0; ++ char *addr_ptrs[MAXADDRS]; ++ unsigned int n; ++ ++ if (getenv("ANDROID_HOSTS_CACHE_DISABLE") != NULL) ++ return NETDB_INTERNAL; ++ ++ switch (af) { ++ case AF_INET: addrlen = NS_INADDRSZ; break; ++ case AF_INET6: addrlen = NS_IN6ADDRSZ; break; ++ default: ++ return NETDB_INTERNAL; ++ } ++ ++ pthread_mutex_lock(&hclock); ++ ++ if (_hcfilemmap() != 0) { ++ ret = NETDB_INTERNAL; ++ goto out; ++ } ++ ++ ent = _hcfindname(host); ++ if (!ent) { ++ ret = HOST_NOT_FOUND; ++ goto out; ++ } ++ ++ cur = ent; ++ do { ++ char addr[16]; ++ char addrstr[MAX_ADDRLEN]; ++ char namestr[MAX_HOSTLEN]; ++ const char *name; ++ ++ hstrcpy(addrstr, hcfile.h_data + cur->addr); ++ if (inet_pton(af, addrstr, &addr) == 1) { ++ char *aligned; ++ /* First match is considered the official hostname */ ++ if (naddrs == 0) { ++ hstrcpy(namestr, hcfile.h_data + cur->name); ++ HENT_SCOPY(info->hp->h_name, namestr, info->buf, info->buflen); ++ } ++ for (name = hcfile.h_data + cur->name; name; name = _hcnextname(name)) { ++ if (!hstrcmp(name, host)) ++ continue; ++ hstrcpy(namestr, name); ++ HENT_SCOPY(aliases[naliases], namestr, info->buf, info->buflen); ++ ++naliases; ++ if (naliases >= MAXALIASES) ++ goto nospc; ++ } ++ aligned = (char *)ALIGN(info->buf); ++ if (info->buf != aligned) { ++ if ((ptrdiff_t)info->buflen < (aligned - info->buf)) ++ goto nospc; ++ info->buflen -= (aligned - info->buf); ++ info->buf = aligned; ++ } ++ HENT_COPY(addr_ptrs[naddrs], addr, addrlen, info->buf, info->buflen); ++ ++naddrs; ++ if (naddrs >= MAXADDRS) ++ goto nospc; ++ } ++ ++ if(cur + 1 >= hcfile.c_data + hcfile.c_len) ++ break; ++ cmp = cmp_hcent_name(cur, cur + 1); ++ cur = cur + 1; ++ } ++ while (!cmp); ++ ++ if (naddrs == 0) { ++ ret = HOST_NOT_FOUND; ++ goto out; ++ } ++ ++ addr_ptrs[naddrs++] = NULL; ++ aliases[naliases++] = NULL; ++ ++ /* hp->h_name already populated */ ++ HENT_ARRAY(info->hp->h_aliases, naliases, info->buf, info->buflen); ++ for (n = 0; n < naliases; ++n) { ++ info->hp->h_aliases[n] = aliases[n]; ++ } ++ info->hp->h_addrtype = af; ++ info->hp->h_length = addrlen; ++ HENT_ARRAY(info->hp->h_addr_list, naddrs, info->buf, info->buflen); ++ for (n = 0; n < naddrs; ++n) { ++ info->hp->h_addr_list[n] = addr_ptrs[n]; ++ } ++ ++out: ++ pthread_mutex_unlock(&hclock); ++ *info->he = ret; ++ return ret; ++ ++nospc: ++ ret = NETDB_INTERNAL; ++ goto out; ++} +diff --git a/libc/dns/net/hosts_cache.h b/libc/dns/net/hosts_cache.h +new file mode 100644 +index 000000000..fa5488f51 +--- /dev/null ++++ b/libc/dns/net/hosts_cache.h +@@ -0,0 +1,23 @@ ++/* ++ * Copyright (C) 2016 The CyanogenMod Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++struct getnamaddr; ++ ++int hc_getaddrinfo(const char *host, const char *service, ++ const struct addrinfo *hints, ++ struct addrinfo **result); ++ ++int hc_gethtbyname(const char *host, int af, struct getnamaddr *info); +diff --git a/libc/dns/net/sethostent.c b/libc/dns/net/sethostent.c +index 483105a95..1399378cd 100644 +--- a/libc/dns/net/sethostent.c ++++ b/libc/dns/net/sethostent.c +@@ -55,6 +55,8 @@ __RCSID("$NetBSD: sethostent.c,v 1.20 2014/03/17 13:24:23 christos Exp $"); + #include "hostent.h" + #include "resolv_private.h" + ++#include "hosts_cache.h" ++ + #ifndef _REENTRANT + void res_close(void); + #endif +@@ -109,6 +111,11 @@ _hf_gethtbyname(void *rv, void *cb_data, va_list ap) + /* NOSTRICT skip string len */(void)va_arg(ap, int); + af = va_arg(ap, int); + ++ int rc = hc_gethtbyname(name, af, info); ++ if (rc != NETDB_INTERNAL) { ++ return (rc == NETDB_SUCCESS ? NS_SUCCESS : NS_NOTFOUND); ++ } ++ + #if 0 + { + res_state res = __res_get_state(); +-- +2.36.0 + diff --git a/Patches/LineageOS-19.1/android_bionic/0003-Hosts_Wildcards.patch b/Patches/LineageOS-19.1/android_bionic/0003-Hosts_Wildcards.patch new file mode 100644 index 00000000..dc489325 --- /dev/null +++ b/Patches/LineageOS-19.1/android_bionic/0003-Hosts_Wildcards.patch @@ -0,0 +1,72 @@ +From 5f63f4b6526c5bf88d5b0676afb6e4917154c96e Mon Sep 17 00:00:00 2001 +From: Tom Marshall +Date: Thu, 16 Jan 2020 13:07:04 -0800 +Subject: [PATCH] bionic: Support wildcards in cached hosts file + +If an exact name is not found in the hosts file and the host name +contains at least one dot, search for entries of the form "*.domain", +where domain is the portion of the host name after the first dot. If +that is not found, repeat using the domain. + +Example: a.b.c.example.com would search for the following in turn: + a.b.c.example.com + *.b.c.example.com + *.c.example.com + *.example.com + *.com + +Change-Id: I4b0bb81699151d5b371850daebf785e35ec9b180 +--- + libc/dns/net/hosts_cache.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/libc/dns/net/hosts_cache.c b/libc/dns/net/hosts_cache.c +index deafb78b7..5038986be 100644 +--- a/libc/dns/net/hosts_cache.c ++++ b/libc/dns/net/hosts_cache.c +@@ -121,7 +121,7 @@ static int cmp_hcent_name(const void *a, const void *b) + return hstrcmp(na, nb); + } + +-static struct hcent *_hcfindname(const char *name) ++static struct hcent *_hcfindname_exact(const char *name) + { + size_t first, last, mid; + struct hcent *cur = NULL; +@@ -162,6 +162,33 @@ found: + return cur; + } + ++static struct hcent *_hcfindname(const char *name) ++{ ++ struct hcent *ent; ++ char namebuf[MAX_HOSTLEN]; ++ char *p; ++ char *dot; ++ ++ ent = _hcfindname_exact(name); ++ if (!ent && strlen(name) < sizeof(namebuf)) { ++ strcpy(namebuf, name); ++ p = namebuf; ++ do { ++ dot = strchr(p, '.'); ++ if (!dot) ++ break; ++ if (dot > p) { ++ *(dot - 1) = '*'; ++ ent = _hcfindname_exact(dot - 1); ++ } ++ p = dot + 1; ++ } ++ while (!ent); ++ } ++ ++ return ent; ++} ++ + /* + * Find next name on line, if any. + * +-- +2.36.0 + diff --git a/Scripts/LineageOS-19.1/Patch.sh b/Scripts/LineageOS-19.1/Patch.sh index 238d0eab..11b0044d 100644 --- a/Scripts/LineageOS-19.1/Patch.sh +++ b/Scripts/LineageOS-19.1/Patch.sh @@ -79,6 +79,8 @@ applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-14.patch" applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-15.patch"; #Move pthread_internal_t behind guard page (GrapheneOS) applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-16.patch"; #Add secondary stack randomization (GrapheneOS) fi; +applyPatch "$DOS_PATCHES/android_bionic/0003-Hosts_Cache.patch"; #Sort and cache hosts file data for fast lookup +applyPatch "$DOS_PATCHES/android_bionic/0003-Hosts_Wildcards.patch"; #Support wildcards in cached hosts file fi; if enterAndClear "bootable/recovery"; then