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

TOMOYO Linux Cross Reference
Linux/security/tomoyo/realpath.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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 ] ~

Diff markup

Differences between /security/tomoyo/realpath.c (Version linux-6.11.5) and /security/tomoyo/realpath.c (Version linux-5.2.21)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2 /*                                                  2 /*
  3  * security/tomoyo/realpath.c                       3  * security/tomoyo/realpath.c
  4  *                                                  4  *
  5  * Copyright (C) 2005-2011  NTT DATA CORPORATI      5  * Copyright (C) 2005-2011  NTT DATA CORPORATION
  6  */                                                 6  */
  7                                                     7 
  8 #include "common.h"                                 8 #include "common.h"
  9 #include <linux/magic.h>                            9 #include <linux/magic.h>
 10 #include <linux/proc_fs.h>                     << 
 11                                                    10 
 12 /**                                                11 /**
 13  * tomoyo_encode2 - Encode binary string to as     12  * tomoyo_encode2 - Encode binary string to ascii string.
 14  *                                                 13  *
 15  * @str:     String in binary format.              14  * @str:     String in binary format.
 16  * @str_len: Size of @str in byte.                 15  * @str_len: Size of @str in byte.
 17  *                                                 16  *
 18  * Returns pointer to @str in ascii format on      17  * Returns pointer to @str in ascii format on success, NULL otherwise.
 19  *                                                 18  *
 20  * This function uses kzalloc(), so caller mus     19  * This function uses kzalloc(), so caller must kfree() if this function
 21  * didn't return NULL.                             20  * didn't return NULL.
 22  */                                                21  */
 23 char *tomoyo_encode2(const char *str, int str_     22 char *tomoyo_encode2(const char *str, int str_len)
 24 {                                                  23 {
 25         int i;                                     24         int i;
 26         int len = 0;                               25         int len = 0;
 27         const char *p = str;                       26         const char *p = str;
 28         char *cp;                                  27         char *cp;
 29         char *cp0;                                 28         char *cp0;
 30                                                    29 
 31         if (!p)                                    30         if (!p)
 32                 return NULL;                       31                 return NULL;
 33         for (i = 0; i < str_len; i++) {            32         for (i = 0; i < str_len; i++) {
 34                 const unsigned char c = p[i];      33                 const unsigned char c = p[i];
 35                                                    34 
 36                 if (c == '\\')                     35                 if (c == '\\')
 37                         len += 2;                  36                         len += 2;
 38                 else if (c > ' ' && c < 127)       37                 else if (c > ' ' && c < 127)
 39                         len++;                     38                         len++;
 40                 else                               39                 else
 41                         len += 4;                  40                         len += 4;
 42         }                                          41         }
 43         len++;                                     42         len++;
 44         /* Reserve space for appending "/". */     43         /* Reserve space for appending "/". */
 45         cp = kzalloc(len + 10, GFP_NOFS);          44         cp = kzalloc(len + 10, GFP_NOFS);
 46         if (!cp)                                   45         if (!cp)
 47                 return NULL;                       46                 return NULL;
 48         cp0 = cp;                                  47         cp0 = cp;
 49         p = str;                                   48         p = str;
 50         for (i = 0; i < str_len; i++) {            49         for (i = 0; i < str_len; i++) {
 51                 const unsigned char c = p[i];      50                 const unsigned char c = p[i];
 52                                                    51 
 53                 if (c == '\\') {                   52                 if (c == '\\') {
 54                         *cp++ = '\\';              53                         *cp++ = '\\';
 55                         *cp++ = '\\';              54                         *cp++ = '\\';
 56                 } else if (c > ' ' && c < 127)     55                 } else if (c > ' ' && c < 127) {
 57                         *cp++ = c;                 56                         *cp++ = c;
 58                 } else {                           57                 } else {
 59                         *cp++ = '\\';              58                         *cp++ = '\\';
 60                         *cp++ = (c >> 6) + '';     59                         *cp++ = (c >> 6) + '';
 61                         *cp++ = ((c >> 3) & 7)     60                         *cp++ = ((c >> 3) & 7) + '';
 62                         *cp++ = (c & 7) + '';      61                         *cp++ = (c & 7) + '';
 63                 }                                  62                 }
 64         }                                          63         }
 65         return cp0;                                64         return cp0;
 66 }                                                  65 }
 67                                                    66 
 68 /**                                                67 /**
 69  * tomoyo_encode - Encode binary string to asc     68  * tomoyo_encode - Encode binary string to ascii string.
 70  *                                                 69  *
 71  * @str: String in binary format.                  70  * @str: String in binary format.
 72  *                                                 71  *
 73  * Returns pointer to @str in ascii format on      72  * Returns pointer to @str in ascii format on success, NULL otherwise.
 74  *                                                 73  *
 75  * This function uses kzalloc(), so caller mus     74  * This function uses kzalloc(), so caller must kfree() if this function
 76  * didn't return NULL.                             75  * didn't return NULL.
 77  */                                                76  */
 78 char *tomoyo_encode(const char *str)               77 char *tomoyo_encode(const char *str)
 79 {                                                  78 {
 80         return str ? tomoyo_encode2(str, strle     79         return str ? tomoyo_encode2(str, strlen(str)) : NULL;
 81 }                                                  80 }
 82                                                    81 
 83 /**                                                82 /**
 84  * tomoyo_get_absolute_path - Get the path of      83  * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
 85  *                                                 84  *
 86  * @path:   Pointer to "struct path".              85  * @path:   Pointer to "struct path".
 87  * @buffer: Pointer to buffer to return value      86  * @buffer: Pointer to buffer to return value in.
 88  * @buflen: Sizeof @buffer.                        87  * @buflen: Sizeof @buffer.
 89  *                                                 88  *
 90  * Returns the buffer on success, an error cod     89  * Returns the buffer on success, an error code otherwise.
 91  *                                                 90  *
 92  * If dentry is a directory, trailing '/' is a     91  * If dentry is a directory, trailing '/' is appended.
 93  */                                                92  */
 94 static char *tomoyo_get_absolute_path(const st     93 static char *tomoyo_get_absolute_path(const struct path *path, char * const buffer,
 95                                       const in     94                                       const int buflen)
 96 {                                                  95 {
 97         char *pos = ERR_PTR(-ENOMEM);              96         char *pos = ERR_PTR(-ENOMEM);
 98                                                    97 
 99         if (buflen >= 256) {                       98         if (buflen >= 256) {
100                 /* go to whatever namespace ro     99                 /* go to whatever namespace root we are under */
101                 pos = d_absolute_path(path, bu    100                 pos = d_absolute_path(path, buffer, buflen - 1);
102                 if (!IS_ERR(pos) && *pos == '/    101                 if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
103                         struct inode *inode =     102                         struct inode *inode = d_backing_inode(path->dentry);
104                                                   103 
105                         if (inode && S_ISDIR(i    104                         if (inode && S_ISDIR(inode->i_mode)) {
106                                 buffer[buflen     105                                 buffer[buflen - 2] = '/';
107                                 buffer[buflen     106                                 buffer[buflen - 1] = '\0';
108                         }                         107                         }
109                 }                                 108                 }
110         }                                         109         }
111         return pos;                               110         return pos;
112 }                                                 111 }
113                                                   112 
114 /**                                               113 /**
115  * tomoyo_get_dentry_path - Get the path of a     114  * tomoyo_get_dentry_path - Get the path of a dentry.
116  *                                                115  *
117  * @dentry: Pointer to "struct dentry".           116  * @dentry: Pointer to "struct dentry".
118  * @buffer: Pointer to buffer to return value     117  * @buffer: Pointer to buffer to return value in.
119  * @buflen: Sizeof @buffer.                       118  * @buflen: Sizeof @buffer.
120  *                                                119  *
121  * Returns the buffer on success, an error cod    120  * Returns the buffer on success, an error code otherwise.
122  *                                                121  *
123  * If dentry is a directory, trailing '/' is a    122  * If dentry is a directory, trailing '/' is appended.
124  */                                               123  */
125 static char *tomoyo_get_dentry_path(struct den    124 static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer,
126                                     const int     125                                     const int buflen)
127 {                                                 126 {
128         char *pos = ERR_PTR(-ENOMEM);             127         char *pos = ERR_PTR(-ENOMEM);
129                                                   128 
130         if (buflen >= 256) {                      129         if (buflen >= 256) {
131                 pos = dentry_path_raw(dentry,     130                 pos = dentry_path_raw(dentry, buffer, buflen - 1);
132                 if (!IS_ERR(pos) && *pos == '/    131                 if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
133                         struct inode *inode =     132                         struct inode *inode = d_backing_inode(dentry);
134                                                   133 
135                         if (inode && S_ISDIR(i    134                         if (inode && S_ISDIR(inode->i_mode)) {
136                                 buffer[buflen     135                                 buffer[buflen - 2] = '/';
137                                 buffer[buflen     136                                 buffer[buflen - 1] = '\0';
138                         }                         137                         }
139                 }                                 138                 }
140         }                                         139         }
141         return pos;                               140         return pos;
142 }                                                 141 }
143                                                   142 
144 /**                                               143 /**
145  * tomoyo_get_local_path - Get the path of a d    144  * tomoyo_get_local_path - Get the path of a dentry.
146  *                                                145  *
147  * @dentry: Pointer to "struct dentry".           146  * @dentry: Pointer to "struct dentry".
148  * @buffer: Pointer to buffer to return value     147  * @buffer: Pointer to buffer to return value in.
149  * @buflen: Sizeof @buffer.                       148  * @buflen: Sizeof @buffer.
150  *                                                149  *
151  * Returns the buffer on success, an error cod    150  * Returns the buffer on success, an error code otherwise.
152  */                                               151  */
153 static char *tomoyo_get_local_path(struct dent    152 static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
154                                    const int b    153                                    const int buflen)
155 {                                                 154 {
156         struct super_block *sb = dentry->d_sb;    155         struct super_block *sb = dentry->d_sb;
157         char *pos = tomoyo_get_dentry_path(den    156         char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen);
158                                                   157 
159         if (IS_ERR(pos))                          158         if (IS_ERR(pos))
160                 return pos;                       159                 return pos;
161         /* Convert from $PID to self if $PID i    160         /* Convert from $PID to self if $PID is current thread. */
162         if (sb->s_magic == PROC_SUPER_MAGIC &&    161         if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
163                 char *ep;                         162                 char *ep;
164                 const pid_t pid = (pid_t) simp    163                 const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
165                 struct pid_namespace *proc_pid << 
166                                                   164 
167                 if (*ep == '/' && pid && pid =    165                 if (*ep == '/' && pid && pid ==
168                     task_tgid_nr_ns(current, p !! 166                     task_tgid_nr_ns(current, sb->s_fs_info)) {
169                         pos = ep - 5;             167                         pos = ep - 5;
170                         if (pos < buffer)         168                         if (pos < buffer)
171                                 goto out;         169                                 goto out;
172                         memmove(pos, "/self",     170                         memmove(pos, "/self", 5);
173                 }                                 171                 }
174                 goto prepend_filesystem_name;     172                 goto prepend_filesystem_name;
175         }                                         173         }
176         /* Use filesystem name for unnamed dev    174         /* Use filesystem name for unnamed devices. */
177         if (!MAJOR(sb->s_dev))                    175         if (!MAJOR(sb->s_dev))
178                 goto prepend_filesystem_name;     176                 goto prepend_filesystem_name;
179         {                                         177         {
180                 struct inode *inode = d_backin    178                 struct inode *inode = d_backing_inode(sb->s_root);
181                                                   179 
182                 /*                                180                 /*
183                  * Use filesystem name if file    181                  * Use filesystem name if filesystem does not support rename()
184                  * operation.                     182                  * operation.
185                  */                               183                  */
186                 if (!inode->i_op->rename)         184                 if (!inode->i_op->rename)
187                         goto prepend_filesyste    185                         goto prepend_filesystem_name;
188         }                                         186         }
189         /* Prepend device name. */                187         /* Prepend device name. */
190         {                                         188         {
191                 char name[64];                    189                 char name[64];
192                 int name_len;                     190                 int name_len;
193                 const dev_t dev = sb->s_dev;      191                 const dev_t dev = sb->s_dev;
194                                                   192 
195                 name[sizeof(name) - 1] = '\0';    193                 name[sizeof(name) - 1] = '\0';
196                 snprintf(name, sizeof(name) -     194                 snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
197                          MINOR(dev));             195                          MINOR(dev));
198                 name_len = strlen(name);          196                 name_len = strlen(name);
199                 pos -= name_len;                  197                 pos -= name_len;
200                 if (pos < buffer)                 198                 if (pos < buffer)
201                         goto out;                 199                         goto out;
202                 memmove(pos, name, name_len);     200                 memmove(pos, name, name_len);
203                 return pos;                       201                 return pos;
204         }                                         202         }
205         /* Prepend filesystem name. */            203         /* Prepend filesystem name. */
206 prepend_filesystem_name:                          204 prepend_filesystem_name:
207         {                                         205         {
208                 const char *name = sb->s_type-    206                 const char *name = sb->s_type->name;
209                 const int name_len = strlen(na    207                 const int name_len = strlen(name);
210                                                   208 
211                 pos -= name_len + 1;              209                 pos -= name_len + 1;
212                 if (pos < buffer)                 210                 if (pos < buffer)
213                         goto out;                 211                         goto out;
214                 memmove(pos, name, name_len);     212                 memmove(pos, name, name_len);
215                 pos[name_len] = ':';              213                 pos[name_len] = ':';
216         }                                         214         }
217         return pos;                               215         return pos;
218 out:                                              216 out:
219         return ERR_PTR(-ENOMEM);                  217         return ERR_PTR(-ENOMEM);
220 }                                                 218 }
221                                                   219 
222 /**                                               220 /**
                                                   >> 221  * tomoyo_get_socket_name - Get the name of a socket.
                                                   >> 222  *
                                                   >> 223  * @path:   Pointer to "struct path".
                                                   >> 224  * @buffer: Pointer to buffer to return value in.
                                                   >> 225  * @buflen: Sizeof @buffer.
                                                   >> 226  *
                                                   >> 227  * Returns the buffer.
                                                   >> 228  */
                                                   >> 229 static char *tomoyo_get_socket_name(const struct path *path, char * const buffer,
                                                   >> 230                                     const int buflen)
                                                   >> 231 {
                                                   >> 232         struct inode *inode = d_backing_inode(path->dentry);
                                                   >> 233         struct socket *sock = inode ? SOCKET_I(inode) : NULL;
                                                   >> 234         struct sock *sk = sock ? sock->sk : NULL;
                                                   >> 235 
                                                   >> 236         if (sk) {
                                                   >> 237                 snprintf(buffer, buflen, "socket:[family=%u:type=%u:protocol=%u]",
                                                   >> 238                          sk->sk_family, sk->sk_type, sk->sk_protocol);
                                                   >> 239         } else {
                                                   >> 240                 snprintf(buffer, buflen, "socket:[unknown]");
                                                   >> 241         }
                                                   >> 242         return buffer;
                                                   >> 243 }
                                                   >> 244 
                                                   >> 245 /**
223  * tomoyo_realpath_from_path - Returns realpat    246  * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
224  *                                                247  *
225  * @path: Pointer to "struct path".               248  * @path: Pointer to "struct path".
226  *                                                249  *
227  * Returns the realpath of the given @path on     250  * Returns the realpath of the given @path on success, NULL otherwise.
228  *                                                251  *
229  * If dentry is a directory, trailing '/' is a    252  * If dentry is a directory, trailing '/' is appended.
230  * Characters out of 0x20 < c < 0x7F range are    253  * Characters out of 0x20 < c < 0x7F range are converted to
231  * \ooo style octal string.                       254  * \ooo style octal string.
232  * Character \ is converted to \\ string.         255  * Character \ is converted to \\ string.
233  *                                                256  *
234  * These functions use kzalloc(), so the calle    257  * These functions use kzalloc(), so the caller must call kfree()
235  * if these functions didn't return NULL.         258  * if these functions didn't return NULL.
236  */                                               259  */
237 char *tomoyo_realpath_from_path(const struct p    260 char *tomoyo_realpath_from_path(const struct path *path)
238 {                                                 261 {
239         char *buf = NULL;                         262         char *buf = NULL;
240         char *name = NULL;                        263         char *name = NULL;
241         unsigned int buf_len = PAGE_SIZE / 2;     264         unsigned int buf_len = PAGE_SIZE / 2;
242         struct dentry *dentry = path->dentry;     265         struct dentry *dentry = path->dentry;
243         struct super_block *sb = dentry->d_sb; !! 266         struct super_block *sb;
244                                                   267 
                                                   >> 268         if (!dentry)
                                                   >> 269                 return NULL;
                                                   >> 270         sb = dentry->d_sb;
245         while (1) {                               271         while (1) {
246                 char *pos;                        272                 char *pos;
247                 struct inode *inode;              273                 struct inode *inode;
248                                                   274 
249                 buf_len <<= 1;                    275                 buf_len <<= 1;
250                 kfree(buf);                       276                 kfree(buf);
251                 buf = kmalloc(buf_len, GFP_NOF    277                 buf = kmalloc(buf_len, GFP_NOFS);
252                 if (!buf)                         278                 if (!buf)
253                         break;                    279                         break;
254                 /* To make sure that pos is '\    280                 /* To make sure that pos is '\0' terminated. */
255                 buf[buf_len - 1] = '\0';          281                 buf[buf_len - 1] = '\0';
256                 /* For "pipe:[\$]" and "socket !! 282                 /* Get better name for socket. */
                                                   >> 283                 if (sb->s_magic == SOCKFS_MAGIC) {
                                                   >> 284                         pos = tomoyo_get_socket_name(path, buf, buf_len - 1);
                                                   >> 285                         goto encode;
                                                   >> 286                 }
                                                   >> 287                 /* For "pipe:[\$]". */
257                 if (dentry->d_op && dentry->d_    288                 if (dentry->d_op && dentry->d_op->d_dname) {
258                         pos = dentry->d_op->d_    289                         pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
259                         goto encode;              290                         goto encode;
260                 }                                 291                 }
261                 inode = d_backing_inode(sb->s_    292                 inode = d_backing_inode(sb->s_root);
262                 /*                                293                 /*
263                  * Get local name for filesyst    294                  * Get local name for filesystems without rename() operation
                                                   >> 295                  * or dentry without vfsmount.
264                  */                               296                  */
265                 if ((!inode->i_op->rename &&   !! 297                 if (!path->mnt ||
                                                   >> 298                     (!inode->i_op->rename &&
266                      !(sb->s_type->fs_flags &     299                      !(sb->s_type->fs_flags & FS_REQUIRES_DEV)))
267                         pos = tomoyo_get_local    300                         pos = tomoyo_get_local_path(path->dentry, buf,
268                                                   301                                                     buf_len - 1);
269                 /* Get absolute name for the r    302                 /* Get absolute name for the rest. */
270                 else {                            303                 else {
271                         pos = tomoyo_get_absol    304                         pos = tomoyo_get_absolute_path(path, buf, buf_len - 1);
272                         /*                        305                         /*
273                          * Fall back to local     306                          * Fall back to local name if absolute name is not
274                          * available.             307                          * available.
275                          */                       308                          */
276                         if (pos == ERR_PTR(-EI    309                         if (pos == ERR_PTR(-EINVAL))
277                                 pos = tomoyo_g    310                                 pos = tomoyo_get_local_path(path->dentry, buf,
278                                                   311                                                             buf_len - 1);
279                 }                                 312                 }
280 encode:                                           313 encode:
281                 if (IS_ERR(pos))                  314                 if (IS_ERR(pos))
282                         continue;                 315                         continue;
283                 name = tomoyo_encode(pos);        316                 name = tomoyo_encode(pos);
284                 break;                            317                 break;
285         }                                         318         }
286         kfree(buf);                               319         kfree(buf);
287         if (!name)                                320         if (!name)
288                 tomoyo_warn_oom(__func__);        321                 tomoyo_warn_oom(__func__);
289         return name;                              322         return name;
290 }                                                 323 }
291                                                   324 
292 /**                                               325 /**
293  * tomoyo_realpath_nofollow - Get realpath of     326  * tomoyo_realpath_nofollow - Get realpath of a pathname.
294  *                                                327  *
295  * @pathname: The pathname to solve.              328  * @pathname: The pathname to solve.
296  *                                                329  *
297  * Returns the realpath of @pathname on succes    330  * Returns the realpath of @pathname on success, NULL otherwise.
298  */                                               331  */
299 char *tomoyo_realpath_nofollow(const char *pat    332 char *tomoyo_realpath_nofollow(const char *pathname)
300 {                                                 333 {
301         struct path path;                         334         struct path path;
302                                                   335 
303         if (pathname && kern_path(pathname, 0,    336         if (pathname && kern_path(pathname, 0, &path) == 0) {
304                 char *buf = tomoyo_realpath_fr    337                 char *buf = tomoyo_realpath_from_path(&path);
305                                                   338 
306                 path_put(&path);                  339                 path_put(&path);
307                 return buf;                       340                 return buf;
308         }                                         341         }
309         return NULL;                              342         return NULL;
310 }                                                 343 }
311                                                   344 

~ [ 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