~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/cachefiles/key.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /* Key to pathname encoder
  3  *
  4  * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
  5  * Written by David Howells (dhowells@redhat.com)
  6  */
  7 
  8 #include <linux/slab.h>
  9 #include "internal.h"
 10 
 11 static const char cachefiles_charmap[64] =
 12         "0123456789"                    /* 0 - 9 */
 13         "abcdefghijklmnopqrstuvwxyz"    /* 10 - 35 */
 14         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    /* 36 - 61 */
 15         "_-"                            /* 62 - 63 */
 16         ;
 17 
 18 static const char cachefiles_filecharmap[256] = {
 19         /* we skip space and tab and control chars */
 20         [33 ... 46] = 1,                /* '!' -> '.' */
 21         /* we skip '/' as it's significant to pathwalk */
 22         [48 ... 127] = 1,               /* '' -> '~' */
 23 };
 24 
 25 static inline unsigned int how_many_hex_digits(unsigned int x)
 26 {
 27         return x ? round_up(ilog2(x) + 1, 4) / 4 : 0;
 28 }
 29 
 30 /*
 31  * turn the raw key into something cooked
 32  * - the key may be up to NAME_MAX in length (including the length word)
 33  *   - "base64" encode the strange keys, mapping 3 bytes of raw to four of
 34  *     cooked
 35  *   - need to cut the cooked key into 252 char lengths (189 raw bytes)
 36  */
 37 bool cachefiles_cook_key(struct cachefiles_object *object)
 38 {
 39         const u8 *key = fscache_get_key(object->cookie), *kend;
 40         unsigned char ch;
 41         unsigned int acc, i, n, nle, nbe, keylen = object->cookie->key_len;
 42         unsigned int b64len, len, print, pad;
 43         char *name, sep;
 44 
 45         _enter(",%u,%*phN", keylen, keylen, key);
 46 
 47         BUG_ON(keylen > NAME_MAX - 3);
 48 
 49         print = 1;
 50         for (i = 0; i < keylen; i++) {
 51                 ch = key[i];
 52                 print &= cachefiles_filecharmap[ch];
 53         }
 54 
 55         /* If the path is usable ASCII, then we render it directly */
 56         if (print) {
 57                 len = 1 + keylen;
 58                 name = kmalloc(len + 1, GFP_KERNEL);
 59                 if (!name)
 60                         return false;
 61 
 62                 name[0] = 'D'; /* Data object type, string encoding */
 63                 memcpy(name + 1, key, keylen);
 64                 goto success;
 65         }
 66 
 67         /* See if it makes sense to encode it as "hex,hex,hex" for each 32-bit
 68          * chunk.  We rely on the key having been padded out to a whole number
 69          * of 32-bit words.
 70          */
 71         n = round_up(keylen, 4);
 72         nbe = nle = 0;
 73         for (i = 0; i < n; i += 4) {
 74                 u32 be = be32_to_cpu(*(__be32 *)(key + i));
 75                 u32 le = le32_to_cpu(*(__le32 *)(key + i));
 76 
 77                 nbe += 1 + how_many_hex_digits(be);
 78                 nle += 1 + how_many_hex_digits(le);
 79         }
 80 
 81         b64len = DIV_ROUND_UP(keylen, 3);
 82         pad = b64len * 3 - keylen;
 83         b64len = 2 + b64len * 4; /* Length if we base64-encode it */
 84         _debug("len=%u nbe=%u nle=%u b64=%u", keylen, nbe, nle, b64len);
 85         if (nbe < b64len || nle < b64len) {
 86                 unsigned int nlen = min(nbe, nle) + 1;
 87                 name = kmalloc(nlen, GFP_KERNEL);
 88                 if (!name)
 89                         return false;
 90                 sep = (nbe <= nle) ? 'S' : 'T'; /* Encoding indicator */
 91                 len = 0;
 92                 for (i = 0; i < n; i += 4) {
 93                         u32 x;
 94                         if (nbe <= nle)
 95                                 x = be32_to_cpu(*(__be32 *)(key + i));
 96                         else
 97                                 x = le32_to_cpu(*(__le32 *)(key + i));
 98                         name[len++] = sep;
 99                         if (x != 0)
100                                 len += snprintf(name + len, nlen - len, "%x", x);
101                         sep = ',';
102                 }
103                 goto success;
104         }
105 
106         /* We need to base64-encode it */
107         name = kmalloc(b64len + 1, GFP_KERNEL);
108         if (!name)
109                 return false;
110 
111         name[0] = 'E';
112         name[1] = '' + pad;
113         len = 2;
114         kend = key + keylen;
115         do {
116                 acc  = *key++;
117                 if (key < kend) {
118                         acc |= *key++ << 8;
119                         if (key < kend)
120                                 acc |= *key++ << 16;
121                 }
122 
123                 name[len++] = cachefiles_charmap[acc & 63];
124                 acc >>= 6;
125                 name[len++] = cachefiles_charmap[acc & 63];
126                 acc >>= 6;
127                 name[len++] = cachefiles_charmap[acc & 63];
128                 acc >>= 6;
129                 name[len++] = cachefiles_charmap[acc & 63];
130         } while (key < kend);
131 
132 success:
133         name[len] = 0;
134         object->d_name = name;
135         object->d_name_len = len;
136         _leave(" = %s", object->d_name);
137         return true;
138 }
139 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php