diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2023-11-27 13:06:55 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2023-11-27 13:06:55 +0100 |
commit | 8dc579d9551d544e7d6d4feee8d951b3ca5d5821 (patch) | |
tree | 2a27dc184448d7987b0ede55588ed07e86a7a696 /lib | |
parent | 914e0cc835e027c5b35d2632f77531fcc70f0d34 (diff) | |
parent | deee811d90c108a8783ad960ddeffe64bacab605 (diff) | |
download | barebox-8dc579d9551d544e7d6d4feee8d951b3ca5d5821.tar.gz barebox-8dc579d9551d544e7d6d4feee8d951b3ca5d5821.tar.xz |
Merge branch 'for-next/prepare-optee'
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 3 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/idr.c | 100 | ||||
-rw-r--r-- | lib/reed_solomon/reed_solomon.c | 2 | ||||
-rw-r--r-- | lib/refcount.c | 34 | ||||
-rw-r--r-- | lib/string.c | 71 |
6 files changed, 211 insertions, 1 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index fbc9fff865..71715ef6e8 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -226,6 +226,9 @@ config GENERIC_ALLOCATOR help Support is curently limited to allocaing a complete mmio-sram at once. +config IDR + bool + endmenu source "lib/Kconfig.hardening" diff --git a/lib/Makefile b/lib/Makefile index 9bb871f94f..38204c8273 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -28,6 +28,7 @@ obj-y += cmdlinepart.o obj-y += recursive_action.o obj-y += make_directory.o obj-y += math.o +obj-$(CONFIG_IDR) += idr.o obj-y += math/ obj-y += uuid.o obj-$(CONFIG_XXHASH) += xxhash.o @@ -71,6 +72,7 @@ obj-$(CONFIG_BAREBOX_LOGO) += logo/ obj-y += reed_solomon/ obj-$(CONFIG_RATP) += ratp.o obj-y += list_sort.o +obj-y += refcount.o obj-y += int_sqrt.o obj-y += parseopt.o obj-y += clz_ctz.o diff --git a/lib/idr.c b/lib/idr.c new file mode 100644 index 0000000000..10a714ac03 --- /dev/null +++ b/lib/idr.c @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * 2002-10-18 written by Jim Houston jim.houston@ccur.com + * Copyright (C) 2002 by Concurrent Computer Corporation + */ + +#include <errno.h> +#include <linux/idr.h> + +struct idr *__idr_find(struct idr *head, int lookup_id) +{ + struct idr *cursor; + + list_for_each_entry(cursor, &head->list, list) { + if (cursor->id == lookup_id) + return cursor; + } + + return NULL; +} + +/** + * idr_for_each() - Iterate through all stored pointers. + * @idr: IDR handle. + * @fn: Function to be called for each pointer. + * @data: Data passed to callback function. + * + * The callback function will be called for each entry in @idr, passing + * the ID, the entry and @data. + * + * If @fn returns anything other than %0, the iteration stops and that + * value is returned from this function. + */ +int idr_for_each(const struct idr *idr, + int (*fn)(int id, void *p, void *data), void *data) +{ + const struct idr *pos, *tmp; + int ret; + + list_for_each_entry_safe(pos, tmp, &idr->list, list) { + ret = fn(pos->id, pos->ptr, data); + if (ret) + return ret; + } + + return 0; +} + +static int idr_compare(struct list_head *a, struct list_head *b) +{ + int id_a = list_entry(a, struct idr, list)->id; + int id_b = list_entry(b, struct idr, list)->id; + + return __compare3(id_a, id_b); +} + +int idr_alloc_one(struct idr *head, void *ptr, int start) +{ + struct idr *idr; + + if (__idr_find(head, start)) + return -EBUSY; + + idr = malloc(sizeof(*idr)); + if (!idr) + return -ENOMEM; + + idr->id = start; + idr->ptr = ptr; + + list_add_sort(&idr->list, &head->list, idr_compare); + + return start; +} + +static void __idr_remove(struct idr *idr) +{ + list_del(&idr->list); + free(idr); +} + +void idr_remove(struct idr *head, int id) +{ + struct idr *idr = __idr_find(head, id); + if (!idr) + return; + + __idr_remove(idr); +} + +void idr_destroy(struct idr *idr) +{ + struct idr *pos, *tmp; + + if (!idr) + return; + + list_for_each_entry_safe(pos, tmp, &idr->list, list) + __idr_remove(pos); +} diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c index 51c67c3c8d..80c0ec4f7a 100644 --- a/lib/reed_solomon/reed_solomon.c +++ b/lib/reed_solomon/reed_solomon.c @@ -44,7 +44,7 @@ #include <module.h> #include <linux/string.h> #include <stdio.h> -#include <asm-generic/errno.h> +#include <linux/errno.h> /* This list holds all currently allocated rs control structures */ static LIST_HEAD (rslist); diff --git a/lib/refcount.c b/lib/refcount.c new file mode 100644 index 0000000000..8c6f98b480 --- /dev/null +++ b/lib/refcount.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Out-of-line refcount functions. + */ + +#include <linux/refcount.h> +#include <linux/printk.h> + +#define REFCOUNT_WARN(str) WARN_ONCE(1, "refcount_t: " str ".\n") + +void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t) +{ + refcount_set(r, REFCOUNT_SATURATED); + + switch (t) { + case REFCOUNT_ADD_NOT_ZERO_OVF: + REFCOUNT_WARN("saturated; leaking memory"); + break; + case REFCOUNT_ADD_OVF: + REFCOUNT_WARN("saturated; leaking memory"); + break; + case REFCOUNT_ADD_UAF: + REFCOUNT_WARN("addition on 0; use-after-free"); + break; + case REFCOUNT_SUB_UAF: + REFCOUNT_WARN("underflow; use-after-free"); + break; + case REFCOUNT_DEC_LEAK: + REFCOUNT_WARN("decrement hit 0; leaking memory"); + break; + default: + REFCOUNT_WARN("unknown saturation event!?"); + } +} diff --git a/lib/string.c b/lib/string.c index 166ef190d6..bf0f0455ab 100644 --- a/lib/string.c +++ b/lib/string.c @@ -22,6 +22,7 @@ #include <linux/types.h> #include <string.h> #include <linux/ctype.h> +#include <asm/word-at-a-time.h> #include <malloc.h> #ifndef __HAVE_ARCH_STRCASECMP @@ -87,6 +88,76 @@ char * strcpy(char * dest,const char *src) #endif EXPORT_SYMBOL(strcpy); +#ifndef __HAVE_ARCH_STRSCPY +ssize_t strscpy(char *dest, const char *src, size_t count) +{ + const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; + size_t max = count; + long res = 0; + + if (count == 0 || WARN_ON_ONCE(count > INT_MAX)) + return -E2BIG; + +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + /* + * If src is unaligned, don't cross a page boundary, + * since we don't know if the next page is mapped. + */ + if ((long)src & (sizeof(long) - 1)) { + size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); + if (limit < max) + max = limit; + } +#else + /* If src or dest is unaligned, don't do word-at-a-time. */ + if (((long) dest | (long) src) & (sizeof(long) - 1)) + max = 0; +#endif + + /* + * read_word_at_a_time() below may read uninitialized bytes after the + * trailing zero and use them in comparisons. Disable this optimization + * under KMSAN to prevent false positive reports. + */ + if (IS_ENABLED(CONFIG_KMSAN)) + max = 0; + + while (max >= sizeof(unsigned long)) { + unsigned long c, data; + + c = read_word_at_a_time(src+res); + if (has_zero(c, &data, &constants)) { + data = prep_zero_mask(c, data, &constants); + data = create_zero_mask(data); + *(unsigned long *)(dest+res) = c & zero_bytemask(data); + return res + find_zero(data); + } + *(unsigned long *)(dest+res) = c; + res += sizeof(unsigned long); + count -= sizeof(unsigned long); + max -= sizeof(unsigned long); + } + + while (count) { + char c; + + c = src[res]; + dest[res] = c; + if (!c) + return res; + res++; + count--; + } + + /* Hit buffer length without finding a NUL; force NUL-termination. */ + if (res) + dest[res-1] = '\0'; + + return -E2BIG; +} +EXPORT_SYMBOL(strscpy); +#endif + /** * stpcpy - Copy a %NUL terminated string, but return pointer to %NUL * @dest: Where to copy the string to |