cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

utf8-core.c (4510B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#include <linux/module.h>
      3#include <linux/kernel.h>
      4#include <linux/string.h>
      5#include <linux/slab.h>
      6#include <linux/parser.h>
      7#include <linux/errno.h>
      8#include <linux/stringhash.h>
      9
     10#include "utf8n.h"
     11
     12int utf8_validate(const struct unicode_map *um, const struct qstr *str)
     13{
     14	if (utf8nlen(um, UTF8_NFDI, str->name, str->len) < 0)
     15		return -1;
     16	return 0;
     17}
     18EXPORT_SYMBOL(utf8_validate);
     19
     20int utf8_strncmp(const struct unicode_map *um,
     21		 const struct qstr *s1, const struct qstr *s2)
     22{
     23	struct utf8cursor cur1, cur2;
     24	int c1, c2;
     25
     26	if (utf8ncursor(&cur1, um, UTF8_NFDI, s1->name, s1->len) < 0)
     27		return -EINVAL;
     28
     29	if (utf8ncursor(&cur2, um, UTF8_NFDI, s2->name, s2->len) < 0)
     30		return -EINVAL;
     31
     32	do {
     33		c1 = utf8byte(&cur1);
     34		c2 = utf8byte(&cur2);
     35
     36		if (c1 < 0 || c2 < 0)
     37			return -EINVAL;
     38		if (c1 != c2)
     39			return 1;
     40	} while (c1);
     41
     42	return 0;
     43}
     44EXPORT_SYMBOL(utf8_strncmp);
     45
     46int utf8_strncasecmp(const struct unicode_map *um,
     47		     const struct qstr *s1, const struct qstr *s2)
     48{
     49	struct utf8cursor cur1, cur2;
     50	int c1, c2;
     51
     52	if (utf8ncursor(&cur1, um, UTF8_NFDICF, s1->name, s1->len) < 0)
     53		return -EINVAL;
     54
     55	if (utf8ncursor(&cur2, um, UTF8_NFDICF, s2->name, s2->len) < 0)
     56		return -EINVAL;
     57
     58	do {
     59		c1 = utf8byte(&cur1);
     60		c2 = utf8byte(&cur2);
     61
     62		if (c1 < 0 || c2 < 0)
     63			return -EINVAL;
     64		if (c1 != c2)
     65			return 1;
     66	} while (c1);
     67
     68	return 0;
     69}
     70EXPORT_SYMBOL(utf8_strncasecmp);
     71
     72/* String cf is expected to be a valid UTF-8 casefolded
     73 * string.
     74 */
     75int utf8_strncasecmp_folded(const struct unicode_map *um,
     76			    const struct qstr *cf,
     77			    const struct qstr *s1)
     78{
     79	struct utf8cursor cur1;
     80	int c1, c2;
     81	int i = 0;
     82
     83	if (utf8ncursor(&cur1, um, UTF8_NFDICF, s1->name, s1->len) < 0)
     84		return -EINVAL;
     85
     86	do {
     87		c1 = utf8byte(&cur1);
     88		c2 = cf->name[i++];
     89		if (c1 < 0)
     90			return -EINVAL;
     91		if (c1 != c2)
     92			return 1;
     93	} while (c1);
     94
     95	return 0;
     96}
     97EXPORT_SYMBOL(utf8_strncasecmp_folded);
     98
     99int utf8_casefold(const struct unicode_map *um, const struct qstr *str,
    100		  unsigned char *dest, size_t dlen)
    101{
    102	struct utf8cursor cur;
    103	size_t nlen = 0;
    104
    105	if (utf8ncursor(&cur, um, UTF8_NFDICF, str->name, str->len) < 0)
    106		return -EINVAL;
    107
    108	for (nlen = 0; nlen < dlen; nlen++) {
    109		int c = utf8byte(&cur);
    110
    111		dest[nlen] = c;
    112		if (!c)
    113			return nlen;
    114		if (c == -1)
    115			break;
    116	}
    117	return -EINVAL;
    118}
    119EXPORT_SYMBOL(utf8_casefold);
    120
    121int utf8_casefold_hash(const struct unicode_map *um, const void *salt,
    122		       struct qstr *str)
    123{
    124	struct utf8cursor cur;
    125	int c;
    126	unsigned long hash = init_name_hash(salt);
    127
    128	if (utf8ncursor(&cur, um, UTF8_NFDICF, str->name, str->len) < 0)
    129		return -EINVAL;
    130
    131	while ((c = utf8byte(&cur))) {
    132		if (c < 0)
    133			return -EINVAL;
    134		hash = partial_name_hash((unsigned char)c, hash);
    135	}
    136	str->hash = end_name_hash(hash);
    137	return 0;
    138}
    139EXPORT_SYMBOL(utf8_casefold_hash);
    140
    141int utf8_normalize(const struct unicode_map *um, const struct qstr *str,
    142		   unsigned char *dest, size_t dlen)
    143{
    144	struct utf8cursor cur;
    145	ssize_t nlen = 0;
    146
    147	if (utf8ncursor(&cur, um, UTF8_NFDI, str->name, str->len) < 0)
    148		return -EINVAL;
    149
    150	for (nlen = 0; nlen < dlen; nlen++) {
    151		int c = utf8byte(&cur);
    152
    153		dest[nlen] = c;
    154		if (!c)
    155			return nlen;
    156		if (c == -1)
    157			break;
    158	}
    159	return -EINVAL;
    160}
    161EXPORT_SYMBOL(utf8_normalize);
    162
    163static const struct utf8data *find_table_version(const struct utf8data *table,
    164		size_t nr_entries, unsigned int version)
    165{
    166	size_t i = nr_entries - 1;
    167
    168	while (version < table[i].maxage)
    169		i--;
    170	if (version > table[i].maxage)
    171		return NULL;
    172	return &table[i];
    173}
    174
    175struct unicode_map *utf8_load(unsigned int version)
    176{
    177	struct unicode_map *um;
    178
    179	um = kzalloc(sizeof(struct unicode_map), GFP_KERNEL);
    180	if (!um)
    181		return ERR_PTR(-ENOMEM);
    182	um->version = version;
    183
    184	um->tables = symbol_request(utf8_data_table);
    185	if (!um->tables)
    186		goto out_free_um;
    187
    188	if (!utf8version_is_supported(um, version))
    189		goto out_symbol_put;
    190	um->ntab[UTF8_NFDI] = find_table_version(um->tables->utf8nfdidata,
    191			um->tables->utf8nfdidata_size, um->version);
    192	if (!um->ntab[UTF8_NFDI])
    193		goto out_symbol_put;
    194	um->ntab[UTF8_NFDICF] = find_table_version(um->tables->utf8nfdicfdata,
    195			um->tables->utf8nfdicfdata_size, um->version);
    196	if (!um->ntab[UTF8_NFDICF])
    197		goto out_symbol_put;
    198	return um;
    199
    200out_symbol_put:
    201	symbol_put(um->tables);
    202out_free_um:
    203	kfree(um);
    204	return ERR_PTR(-EINVAL);
    205}
    206EXPORT_SYMBOL(utf8_load);
    207
    208void utf8_unload(struct unicode_map *um)
    209{
    210	if (um) {
    211		symbol_put(utf8_data_table);
    212		kfree(um);
    213	}
    214}
    215EXPORT_SYMBOL(utf8_unload);
    216
    217MODULE_LICENSE("GPL v2");