From 57ac3477a35b2ee8e2e46f5fa83239604266e24b Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Wed, 19 Oct 2022 11:14:16 +0200 Subject: [PATCH 1/2] Validate maglev shm --- src/lib/log.c | 4 ++-- src/lib/maglevdyn.c | 24 ++++++++++++++++++++++++ src/lib/maglevdyn.h | 11 +++++++++++ src/lib/shmem.c | 12 ++++++++---- src/lib/shmem.h | 6 +++--- src/nfqlb/cmdConfig.c | 10 ++++++++-- src/nfqlb/cmdFlowLb-test.c | 2 +- src/nfqlb/cmdFlowLb.c | 13 ++++++++++--- src/nfqlb/cmdFwmark.c | 2 +- src/nfqlb/cmdLb.c | 6 +++--- src/nfqlb/cmdShm.c | 9 ++++++--- 11 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/lib/log.c b/src/lib/log.c index accf5a1..09800e1 100644 --- a/src/lib/log.c +++ b/src/lib/log.c @@ -66,11 +66,11 @@ int logp(const char *fmt, ...) void logConfigShm(char const* name) { - logconfig = mapSharedData(name, O_RDWR); + logconfig = mapSharedData(name, O_RDWR, NULL); if (logconfig != NULL) return; createSharedDataOrDie(name, &default_config, sizeof(struct LogConfig)); - logconfig = mapSharedDataOrDie(name, O_RDWR); + logconfig = mapSharedDataOrDie(name, O_RDWR, NULL); } __attribute__ ((__constructor__)) static void loginit(void) { diff --git a/src/lib/maglevdyn.c b/src/lib/maglevdyn.c index 07f8c77..8f8e58c 100644 --- a/src/lib/maglevdyn.c +++ b/src/lib/maglevdyn.c @@ -50,6 +50,30 @@ void magDataDyn_init(unsigned M, unsigned N, void* mem, unsigned len) magDataDyn_free(&m); } +int magDataDyn_validate(void* mem, size_t len) +{ + if (len < sizeof(struct MagDataDynInternal)) + return -1; + struct MagDataDynInternal* mi = mem; + // M and N may be mutating in shm so copy them ASAP + unsigned M, N; + M = mi->M; + N = mi->N; + if (M < 3) + return -1; + return 0; + if (N == 0) + return -1; + if (N > M) + return -1; + if (M != primeBelow(M)) + return -1; + // len may be higher, but this validation is stricter + if (len != magDataDyn_len(M, N)) + return -1; + return 0; +} + void magDataDyn_map(struct MagDataDyn* m, void* mem) { struct MagDataDynInternal* mi = mem; diff --git a/src/lib/maglevdyn.h b/src/lib/maglevdyn.h index dd1f069..6238032 100644 --- a/src/lib/maglevdyn.h +++ b/src/lib/maglevdyn.h @@ -1,5 +1,11 @@ +/* + SPDX-License-Identifier: Apache-2.0 + Copyright (c) 2021-2022 Nordix Foundation +*/ #pragma once +#include + struct MagDataDyn { unsigned M, N; int *lookup; @@ -20,6 +26,11 @@ unsigned magDataDyn_len(unsigned M, unsigned N); */ void magDataDyn_init(unsigned M, unsigned N, void* mem, unsigned len); +/* + Validate that a memory area is MagDataDyn compatible +*/ +int magDataDyn_validate(void* mem, size_t len); + /* Map to a memory area that may be in shared mem. Must call magDataDyn_free() to free allocated memory. diff --git a/src/lib/shmem.c b/src/lib/shmem.c index db2be87..ee029ab 100644 --- a/src/lib/shmem.c +++ b/src/lib/shmem.c @@ -26,7 +26,7 @@ void createSharedDataOrDie(char const* name, void* data, size_t len) die("createSharedData: %s\n", strerror(errno)); } } -void* mapSharedData(char const* name, int mode) +void* mapSharedData(char const* name, int mode, size_t* len) { int fd = shm_open(name, mode, (mode == O_RDONLY)?0400:0600); if (fd < 0) @@ -34,6 +34,8 @@ void* mapSharedData(char const* name, int mode) struct stat statbuf; if (fstat(fd, &statbuf) != 0) die("fstat shared mem; %s\n", name); + if (len != NULL) + *len = statbuf.st_size; void* m = mmap( NULL, statbuf.st_size, (mode == O_RDONLY)?PROT_READ:PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); @@ -43,14 +45,14 @@ void* mapSharedData(char const* name, int mode) } return m; } -void* mapSharedDataOrDie(char const* name, int mode) +void* mapSharedDataOrDie(char const* name, int mode, size_t* len) { - void* m = mapSharedData(name, mode); + void* m = mapSharedData(name, mode, len); if (m == NULL) die("FAILED mapSharedData: %s\n", name); return m; } -void* mapSharedDataRead(char const* name, /*out*/int* _fd) +void* mapSharedDataRead(char const* name, /*out*/int* _fd, size_t* len) { int fd = shm_open(name, O_RDONLY, 0400); if (fd < 0) @@ -58,6 +60,8 @@ void* mapSharedDataRead(char const* name, /*out*/int* _fd) struct stat statbuf; if (fstat(fd, &statbuf) != 0) die("fstat shared mem; %s\n", name); + if (len != NULL) + *len = statbuf.st_size; void* m = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); if (m == MAP_FAILED) { close(fd); diff --git a/src/lib/shmem.h b/src/lib/shmem.h index cb3487b..0d3425e 100644 --- a/src/lib/shmem.h +++ b/src/lib/shmem.h @@ -9,7 +9,7 @@ int createSharedData(char const* name, void* data, size_t len); void createSharedDataOrDie(char const* name, void* data, size_t len); -void* mapSharedData(char const* name, int mode); -void* mapSharedDataOrDie(char const* name, int mode); -void* mapSharedDataRead(char const* name, /*out*/int* fd); +void* mapSharedData(char const* name, int mode, size_t* len); +void* mapSharedDataOrDie(char const* name, int mode, size_t* len); +void* mapSharedDataRead(char const* name, /*out*/int* fd, size_t* len); diff --git a/src/nfqlb/cmdConfig.c b/src/nfqlb/cmdConfig.c index 189b6d3..952ba3f 100644 --- a/src/nfqlb/cmdConfig.c +++ b/src/nfqlb/cmdConfig.c @@ -29,7 +29,10 @@ static int cmdActivate(int argc, char **argv) argc -= nopt; argv += nopt; struct SharedData* s; - s = mapSharedDataOrDie(shm, O_RDWR); + size_t len; + s = mapSharedDataOrDie(shm, O_RDWR, &len); + if (magDataDyn_validate(s->mem, len - sizeof(struct SharedData)) != 0) + die("Shm invalid; %s\n", shm); struct MagDataDyn magd; magDataDyn_map(&magd, s->mem); @@ -88,7 +91,10 @@ static int cmdDeactivate(int argc, char **argv) argc -= nopt; argv += nopt; struct SharedData* s; - s = mapSharedDataOrDie(shm, O_RDWR); + size_t len; + s = mapSharedDataOrDie(shm, O_RDWR, &len); + if (magDataDyn_validate(s->mem, len - sizeof(struct SharedData)) != 0) + die("Shm invalid; %s\n", shm); struct MagDataDyn magd; magDataDyn_map(&magd, s->mem); diff --git a/src/nfqlb/cmdFlowLb-test.c b/src/nfqlb/cmdFlowLb-test.c index 1574137..096a5de 100644 --- a/src/nfqlb/cmdFlowLb-test.c +++ b/src/nfqlb/cmdFlowLb-test.c @@ -222,7 +222,7 @@ static void initShm( s->ownFwmark = ownFw; createSharedDataOrDie(name, s, sizeof(struct SharedData) + len); free(s); - s = mapSharedDataOrDie(name, O_RDWR); + s = mapSharedDataOrDie(name, O_RDWR, NULL); magDataDyn_init(m, n, s->mem, len); } diff --git a/src/nfqlb/cmdFlowLb.c b/src/nfqlb/cmdFlowLb.c index 30da258..bfaab16 100644 --- a/src/nfqlb/cmdFlowLb.c +++ b/src/nfqlb/cmdFlowLb.c @@ -279,7 +279,7 @@ static int cmdFlowLb(int argc, char **argv) logTraceServer(trace_address); if (lbShm != NULL) { - slb = mapSharedDataOrDie(lbShm, O_RDONLY); + slb = mapSharedDataOrDie(lbShm, O_RDONLY, NULL); magDataDyn_map(&magdlb, slb->mem); } @@ -296,7 +296,7 @@ static int cmdFlowLb(int argc, char **argv) sft = calloc(1, sizeof(*sft)); createSharedDataOrDie(ftShm, sft, sizeof(*sft)); free(sft); - sft = mapSharedDataOrDie(ftShm, O_RDWR); + sft = mapSharedDataOrDie(ftShm, O_RDWR, NULL); // Get MTU from the ingress device int mtu = atoi(mtuOpt); @@ -432,12 +432,19 @@ STATIC struct LoadBalancer* loadbalancerFindOrCreate(char const* target) // Not found, create a new LB trace(TRACE_TARGET, "Creating LB; %s\n", target); int fd; - struct SharedData* st = mapSharedDataRead(target, &fd); + size_t len; + struct SharedData* st = mapSharedDataRead(target, &fd, &len); if (st == NULL) { UNLOCK(lblistLock); trace(TRACE_TARGET, "Map shm failed; %s\n", target); return NULL; } + if (magDataDyn_validate(st->mem, len - sizeof(struct SharedData)) != 0) { + UNLOCK(lblistLock); + trace(TRACE_TARGET, "Shm invalid; %s\n", target); + return NULL; + } + lb = MALLOC(lb); lb->target = strdup(target); diff --git a/src/nfqlb/cmdFwmark.c b/src/nfqlb/cmdFwmark.c index 368c115..30e3d46 100644 --- a/src/nfqlb/cmdFwmark.c +++ b/src/nfqlb/cmdFwmark.c @@ -60,7 +60,7 @@ static int cmdFwmark(int argc, char **argv) if (shm != NULL) { struct SharedData* s = NULL; - s = mapSharedDataOrDie(shm, O_RDWR); + s = mapSharedDataOrDie(shm, O_RDWR, NULL); struct MagDataDyn magd; magDataDyn_map(&magd, s->mem); unsigned index = hash % magd.M; diff --git a/src/nfqlb/cmdLb.c b/src/nfqlb/cmdLb.c index 627d225..f70b019 100644 --- a/src/nfqlb/cmdLb.c +++ b/src/nfqlb/cmdLb.c @@ -161,10 +161,10 @@ static int cmdLb(int argc, char **argv) logConfigShm(TRACE_SHM); logTraceServer(trace_address); - st = mapSharedDataOrDie(targetShm, O_RDONLY); + st = mapSharedDataOrDie(targetShm, O_RDONLY, NULL); magDataDyn_map(&magd, st->mem); if (lbShm != NULL) { - slb = mapSharedDataOrDie(lbShm, O_RDONLY); + slb = mapSharedDataOrDie(lbShm, O_RDONLY, NULL); magDataDyn_map(&magdlb, slb->mem); } notargets_fw = atoi(notargets_fwmark); @@ -173,7 +173,7 @@ static int cmdLb(int argc, char **argv) sft = calloc(1, sizeof(*sft)); createSharedDataOrDie(ftShm, sft, sizeof(*sft)); free(sft); - sft = mapSharedDataOrDie(ftShm, O_RDWR); + sft = mapSharedDataOrDie(ftShm, O_RDWR, NULL); // Get MTU from the ingress device int mtu = atoi(mtuOpt); diff --git a/src/nfqlb/cmdShm.c b/src/nfqlb/cmdShm.c index 5d9ca98..8b3f532 100644 --- a/src/nfqlb/cmdShm.c +++ b/src/nfqlb/cmdShm.c @@ -27,7 +27,7 @@ static void initShm( s->ownFwmark = ownFw; createSharedDataOrDie(name, s, sizeof(struct SharedData) + len); free(s); - s = mapSharedDataOrDie(name, O_RDWR); + s = mapSharedDataOrDie(name, O_RDWR, NULL); magDataDyn_init(m, n, s->mem, len); } @@ -109,7 +109,10 @@ static int cmdShow(int argc, char **argv) }; (void)parseOptionsOrDie(argc, argv, options); struct SharedData* s; - s = mapSharedDataOrDie(shm, O_RDONLY); + size_t len; + s = mapSharedDataOrDie(shm, O_RDONLY, &len); + if (magDataDyn_validate(s->mem, len - sizeof(struct SharedData)) != 0) + die("Shm invalid; %s\n", shm); if (s == NULL) die("Failed to open shared mem; %s\n", shm); printf("Shm: %s\n", shm); @@ -144,7 +147,7 @@ static int cmdStats(int argc, char **argv) {0, 0, 0, 0} }; (void)parseOptionsOrDie(argc, argv, options); - struct fragStats* sft = mapSharedDataOrDie(ftShm, O_RDONLY); + struct fragStats* sft = mapSharedDataOrDie(ftShm, O_RDONLY, NULL); fragPrintStats(sft); return 0; } From d430e6992e06251a2ea756e55d1f966f8c6137f4 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Wed, 9 Nov 2022 08:47:34 +0100 Subject: [PATCH 2/2] ipu; add linklocal command --- src/ipu/ipu.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/ipu/ipu.c b/src/ipu/ipu.c index a89293b..b2d8d11 100644 --- a/src/ipu/ipu.c +++ b/src/ipu/ipu.c @@ -7,8 +7,43 @@ #include #include #include +#include #include +static int cmdLinklocal(int argc, char* argv[]) +{ + struct Option options[] = { + {"help", NULL, 0, + "linklocal \n" + " Compute an ipv6 link-local address using EUI-64" + }, + {0, 0, 0, 0} + }; + int n = parseOptionsOrDie(argc, argv, options); + argc -= n; argv += n; + if (argc < 1) + die("No mac-address\n"); + struct ether_addr* mac = ether_aton(*argv); + if (mac == NULL) + die("Invalid MAC [%s]\n", *argv); + mac->ether_addr_octet[0] ^= 0x02; /* flip bit 7 */ + + struct in6_addr addr = {0}; + addr.s6_addr32[0] = htonl(0xfe800000); + addr.s6_addr[8] = mac->ether_addr_octet[0]; + addr.s6_addr[9] = mac->ether_addr_octet[1]; + addr.s6_addr[10] = mac->ether_addr_octet[2]; + addr.s6_addr[11] = 0xff; + addr.s6_addr[12] = 0xfe; + addr.s6_addr[13] = mac->ether_addr_octet[3]; + addr.s6_addr[14] = mac->ether_addr_octet[4]; + addr.s6_addr[15] = mac->ether_addr_octet[5]; + char strbuf[INET6_ADDRSTRLEN+1]; + inet_ntop(AF_INET6, &addr, strbuf, sizeof(strbuf)); + printf("%s\n", strbuf); + return 0; +} + static int cmdMakeip(int argc, char* argv[]) { char const* opt_cidr = NULL; @@ -305,6 +340,7 @@ static int cmdVersion(int argc, char **argv) } __attribute__ ((__constructor__)) static void addCommands(void) { + addCmd("linklocal", cmdLinklocal); addCmd("makeip", cmdMakeip); addCmd("contains", cmdContains); addCmd("version", cmdVersion);