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

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

Version: ~ [ linux-5.10-rc6 ] ~ [ linux-5.9.12 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.81 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.161 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.210 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.247 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.247 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Key to pathname encoder
  2  *
  3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  4  * Written by David Howells (dhowells@redhat.com)
  5  *
  6  * This program is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU General Public Licence
  8  * as published by the Free Software Foundation; either version
  9  * 2 of the Licence, or (at your option) any later version.
 10  */
 11 
 12 #include <linux/slab.h>
 13 #include "internal.h"
 14 
 15 static const char cachefiles_charmap[64] =
 16         "0123456789"                    /* 0 - 9 */
 17         "abcdefghijklmnopqrstuvwxyz"    /* 10 - 35 */
 18         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    /* 36 - 61 */
 19         "_-"                            /* 62 - 63 */
 20         ;
 21 
 22 static const char cachefiles_filecharmap[256] = {
 23         /* we skip space and tab and control chars */
 24         [33 ... 46] = 1,                /* '!' -> '.' */
 25         /* we skip '/' as it's significant to pathwalk */
 26         [48 ... 127] = 1,               /* '' -> '~' */
 27 };
 28 
 29 /*
 30  * turn the raw key into something cooked
 31  * - the raw key should include the length in the two bytes at the front
 32  * - the key may be up to 514 bytes 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 char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type)
 38 {
 39         unsigned char csum, ch;
 40         unsigned int acc;
 41         char *key;
 42         int loop, len, max, seg, mark, print;
 43 
 44         _enter(",%d", keylen);
 45 
 46         BUG_ON(keylen < 2 || keylen > 514);
 47 
 48         csum = raw[0] + raw[1];
 49         print = 1;
 50         for (loop = 2; loop < keylen; loop++) {
 51                 ch = raw[loop];
 52                 csum += ch;
 53                 print &= cachefiles_filecharmap[ch];
 54         }
 55 
 56         if (print) {
 57                 /* if the path is usable ASCII, then we render it directly */
 58                 max = keylen - 2;
 59                 max += 2;       /* two base64'd length chars on the front */
 60                 max += 5;       /* @checksum/M */
 61                 max += 3 * 2;   /* maximum number of segment dividers (".../M")
 62                                  * is ((514 + 251) / 252) = 3
 63                                  */
 64                 max += 1;       /* NUL on end */
 65         } else {
 66                 /* calculate the maximum length of the cooked key */
 67                 keylen = (keylen + 2) / 3;
 68 
 69                 max = keylen * 4;
 70                 max += 5;       /* @checksum/M */
 71                 max += 3 * 2;   /* maximum number of segment dividers (".../M")
 72                                  * is ((514 + 188) / 189) = 3
 73                                  */
 74                 max += 1;       /* NUL on end */
 75         }
 76 
 77         max += 1;       /* 2nd NUL on end */
 78 
 79         _debug("max: %d", max);
 80 
 81         key = kmalloc(max, cachefiles_gfp);
 82         if (!key)
 83                 return NULL;
 84 
 85         len = 0;
 86 
 87         /* build the cooked key */
 88         sprintf(key, "@%02x%c+", (unsigned) csum, 0);
 89         len = 5;
 90         mark = len - 1;
 91 
 92         if (print) {
 93                 acc = *(uint16_t *) raw;
 94                 raw += 2;
 95 
 96                 key[len + 1] = cachefiles_charmap[acc & 63];
 97                 acc >>= 6;
 98                 key[len] = cachefiles_charmap[acc & 63];
 99                 len += 2;
100 
101                 seg = 250;
102                 for (loop = keylen; loop > 0; loop--) {
103                         if (seg <= 0) {
104                                 key[len++] = '\0';
105                                 mark = len;
106                                 key[len++] = '+';
107                                 seg = 252;
108                         }
109 
110                         key[len++] = *raw++;
111                         ASSERT(len < max);
112                 }
113 
114                 switch (type) {
115                 case FSCACHE_COOKIE_TYPE_INDEX:         type = 'I';     break;
116                 case FSCACHE_COOKIE_TYPE_DATAFILE:      type = 'D';     break;
117                 default:                                type = 'S';     break;
118                 }
119         } else {
120                 seg = 252;
121                 for (loop = keylen; loop > 0; loop--) {
122                         if (seg <= 0) {
123                                 key[len++] = '\0';
124                                 mark = len;
125                                 key[len++] = '+';
126                                 seg = 252;
127                         }
128 
129                         acc = *raw++;
130                         acc |= *raw++ << 8;
131                         acc |= *raw++ << 16;
132 
133                         _debug("acc: %06x", acc);
134 
135                         key[len++] = cachefiles_charmap[acc & 63];
136                         acc >>= 6;
137                         key[len++] = cachefiles_charmap[acc & 63];
138                         acc >>= 6;
139                         key[len++] = cachefiles_charmap[acc & 63];
140                         acc >>= 6;
141                         key[len++] = cachefiles_charmap[acc & 63];
142 
143                         ASSERT(len < max);
144                 }
145 
146                 switch (type) {
147                 case FSCACHE_COOKIE_TYPE_INDEX:         type = 'J';     break;
148                 case FSCACHE_COOKIE_TYPE_DATAFILE:      type = 'E';     break;
149                 default:                                type = 'T';     break;
150                 }
151         }
152 
153         key[mark] = type;
154         key[len++] = 0;
155         key[len] = 0;
156 
157         _leave(" = %p %d", key, len);
158         return key;
159 }
160 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp