Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/caitsith-patch/security/caitsith/realpath.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 386 - (hide annotations) (download) (as text)
Mon Nov 13 11:36:37 2023 UTC (4 months, 4 weeks ago) by kumaneko
File MIME type: text/x-csrc
File size: 16949 byte(s)


1 kumaneko 2 /*
2 kumaneko 7 * security/caitsith/realpath.c
3 kumaneko 2 *
4     * Copyright (C) 2005-2012 NTT DATA CORPORATION
5     *
6 kumaneko 378 * Version: 0.2.11 2023/05/27
7 kumaneko 2 */
8    
9     #include "internal.h"
10    
11     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
12     #include <linux/nsproxy.h>
13     #include <linux/mnt_namespace.h>
14     #endif
15 kumaneko 324 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
16     #include <linux/proc_fs.h>
17     #endif
18 kumaneko 2
19     /***** SECTION1: Constants definition *****/
20    
21     /***** SECTION2: Structure definition *****/
22    
23     /***** SECTION3: Prototype definition section *****/
24    
25 kumaneko 139 static char *cs_get_absolute_path(const struct path *path, char * const buffer,
26 kumaneko 101 const int buflen);
27     static char *cs_get_dentry_path(struct dentry *dentry, char * const buffer,
28 kumaneko 2 const int buflen);
29 kumaneko 101 static char *cs_get_local_path(struct dentry *dentry, char * const buffer,
30     const int buflen);
31     static int cs_const_part_length(const char *filename);
32 kumaneko 2
33     /***** SECTION4: Standalone functions section *****/
34    
35     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
36    
37     /**
38 kumaneko 101 * cs_realpath_lock - Take locks for __d_path().
39 kumaneko 2 *
40     * Returns nothing.
41     */
42 kumaneko 101 static inline void cs_realpath_lock(void)
43 kumaneko 2 {
44     /* dcache_lock is locked by __d_path(). */
45     /* vfsmount_lock is locked by __d_path(). */
46     }
47    
48     /**
49 kumaneko 101 * cs_realpath_unlock - Release locks for __d_path().
50 kumaneko 2 *
51     * Returns nothing.
52     */
53 kumaneko 101 static inline void cs_realpath_unlock(void)
54 kumaneko 2 {
55     /* vfsmount_lock is unlocked by __d_path(). */
56     /* dcache_lock is unlocked by __d_path(). */
57     }
58    
59     #elif LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 36)
60    
61     /**
62 kumaneko 101 * cs_realpath_lock - Take locks for __d_path().
63 kumaneko 2 *
64     * Returns nothing.
65     */
66 kumaneko 101 static inline void cs_realpath_lock(void)
67 kumaneko 2 {
68     spin_lock(&dcache_lock);
69     /* vfsmount_lock is locked by __d_path(). */
70     }
71    
72     /**
73 kumaneko 101 * cs_realpath_unlock - Release locks for __d_path().
74 kumaneko 2 *
75     * Returns nothing.
76     */
77 kumaneko 101 static inline void cs_realpath_unlock(void)
78 kumaneko 2 {
79     /* vfsmount_lock is unlocked by __d_path(). */
80     spin_unlock(&dcache_lock);
81     }
82    
83     #elif defined(D_PATH_DISCONNECT) && !defined(CONFIG_SUSE_KERNEL)
84    
85     /**
86 kumaneko 101 * cs_realpath_lock - Take locks for __d_path().
87 kumaneko 2 *
88     * Returns nothing.
89     *
90     * Original unambiguous-__d_path.diff in patches.apparmor.tar.bz2 inversed the
91     * order of holding dcache_lock and vfsmount_lock. That patch was applied on
92     * (at least) SUSE 11.1 and Ubuntu 8.10 and Ubuntu 9.04 kernels.
93     *
94     * However, that patch was updated to use original order and the updated patch
95     * is applied to (as far as I know) only SUSE kernels.
96     *
97     * Therefore, I need to use original order for SUSE 11.1 kernels and inversed
98     * order for other kernels. I detect it by checking D_PATH_DISCONNECT and
99     * CONFIG_SUSE_KERNEL. I don't know whether other distributions are using the
100     * updated patch or not. If you got deadlock, check fs/dcache.c for locking
101     * order, and add " && 0" to this "#elif " block if fs/dcache.c uses original
102     * order.
103     */
104 kumaneko 101 static inline void cs_realpath_lock(void)
105 kumaneko 2 {
106 kumaneko 7 spin_lock(caitsith_exports.vfsmount_lock);
107 kumaneko 2 spin_lock(&dcache_lock);
108     }
109    
110     /**
111 kumaneko 101 * cs_realpath_unlock - Release locks for __d_path().
112 kumaneko 2 *
113     * Returns nothing.
114     */
115 kumaneko 101 static inline void cs_realpath_unlock(void)
116 kumaneko 2 {
117     spin_unlock(&dcache_lock);
118 kumaneko 7 spin_unlock(caitsith_exports.vfsmount_lock);
119 kumaneko 2 }
120    
121     #else
122    
123     /**
124 kumaneko 101 * cs_realpath_lock - Take locks for __d_path().
125 kumaneko 2 *
126     * Returns nothing.
127     */
128 kumaneko 101 static inline void cs_realpath_lock(void)
129 kumaneko 2 {
130     spin_lock(&dcache_lock);
131 kumaneko 7 spin_lock(caitsith_exports.vfsmount_lock);
132 kumaneko 2 }
133    
134     /**
135 kumaneko 101 * cs_realpath_unlock - Release locks for __d_path().
136 kumaneko 2 *
137     * Returns nothing.
138     */
139 kumaneko 101 static inline void cs_realpath_unlock(void)
140 kumaneko 2 {
141 kumaneko 7 spin_unlock(caitsith_exports.vfsmount_lock);
142 kumaneko 2 spin_unlock(&dcache_lock);
143     }
144    
145     #endif
146    
147     /***** SECTION5: Variables definition section *****/
148    
149     /***** SECTION6: Dependent functions section *****/
150    
151     /**
152 kumaneko 101 * cs_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
153 kumaneko 2 *
154     * @path: Pointer to "struct path".
155     * @buffer: Pointer to buffer to return value in.
156     * @buflen: Sizeof @buffer.
157     *
158     * Returns the buffer on success, an error code otherwise.
159     *
160     * Caller holds the dcache_lock and vfsmount_lock.
161     * Based on __d_path() in fs/dcache.c
162     */
163 kumaneko 139 static char *cs_get_absolute_path(const struct path *path, char * const buffer,
164 kumaneko 101 const int buflen)
165 kumaneko 2 {
166     #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
167     if (buflen < 256)
168     return ERR_PTR(-ENOMEM);
169 kumaneko 7 return caitsith_exports.d_absolute_path(path, buffer, buflen - 1);
170 kumaneko 2 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
171     /*
172     * __d_path() will start returning NULL by backporting commit 02125a82
173     * "fix apparmor dereferencing potentially freed dentry, sanitize
174     * __d_path() API".
175     *
176     * Unfortunately, __d_path() after applying that commit always returns
177     * NULL when root is empty. d_absolute_path() is provided for TOMOYO
178 kumaneko 101 * 2.x and AppArmor but CaitSith does not use it, for CaitSith
179 kumaneko 2 * might be built as a loadable kernel module and there is no warrantee
180 kumaneko 101 * that CaitSith is recompiled after applying that commit. Also,
181 kumaneko 2 * I don't want to search /proc/kallsyms for d_absolute_path() because
182 kumaneko 101 * I want to keep CaitSith architecture independent. Thus, supply
183 kumaneko 2 * non empty root like AppArmor's d_namespace_path() did.
184     */
185 kumaneko 101 static bool cs_no_empty;
186 kumaneko 2 char *pos;
187 kumaneko 211
188 kumaneko 2 if (buflen < 256)
189     return ERR_PTR(-ENOMEM);
190 kumaneko 101 if (!cs_no_empty) {
191 kumaneko 2 struct path root = { };
192 kumaneko 211
193 kumaneko 7 pos = caitsith_exports.__d_path(path, &root, buffer,
194 kumaneko 101 buflen - 1);
195 kumaneko 2 } else {
196     pos = NULL;
197     }
198     if (!pos) {
199     struct task_struct *task = current;
200     struct path root;
201     struct path tmp;
202 kumaneko 211
203 kumaneko 2 spin_lock(&task->fs->lock);
204     root.mnt = task->nsproxy->mnt_ns->root;
205     root.dentry = root.mnt->mnt_root;
206     path_get(&root);
207     spin_unlock(&task->fs->lock);
208     tmp = root;
209 kumaneko 7 pos = caitsith_exports.__d_path(path, &tmp, buffer,
210 kumaneko 101 buflen - 1);
211 kumaneko 2 path_put(&root);
212     if (pos)
213     return pos;
214     /* Remember if __d_path() needs non empty root. */
215 kumaneko 101 cs_no_empty = true;
216 kumaneko 2 pos = ERR_PTR(-EINVAL);
217     }
218     return pos;
219     #else
220     char *pos = buffer + buflen - 1;
221     struct dentry *dentry = path->dentry;
222     struct vfsmount *vfsmnt = path->mnt;
223     const char *name;
224     int len;
225    
226     if (buflen < 256)
227     goto out;
228    
229     *pos = '\0';
230     for (;;) {
231     struct dentry *parent;
232 kumaneko 211
233 kumaneko 2 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
234     if (vfsmnt->mnt_parent == vfsmnt)
235     break;
236     dentry = vfsmnt->mnt_mountpoint;
237     vfsmnt = vfsmnt->mnt_parent;
238     continue;
239     }
240     parent = dentry->d_parent;
241     name = dentry->d_name.name;
242     len = dentry->d_name.len;
243     pos -= len;
244     if (pos <= buffer)
245     goto out;
246     memmove(pos, name, len);
247     *--pos = '/';
248     dentry = parent;
249     }
250     if (*pos == '/')
251     pos++;
252     len = dentry->d_name.len;
253     pos -= len;
254     if (pos < buffer)
255     goto out;
256     memmove(pos, dentry->d_name.name, len);
257     return pos;
258     out:
259     return ERR_PTR(-ENOMEM);
260     #endif
261     }
262    
263     /**
264 kumaneko 101 * cs_get_dentry_path - Get the path of a dentry.
265 kumaneko 2 *
266     * @dentry: Pointer to "struct dentry".
267     * @buffer: Pointer to buffer to return value in.
268     * @buflen: Sizeof @buffer.
269     *
270     * Returns the buffer on success, an error code otherwise.
271     *
272     * Based on dentry_path() in fs/dcache.c
273     */
274 kumaneko 101 static char *cs_get_dentry_path(struct dentry *dentry, char * const buffer,
275     const int buflen)
276 kumaneko 2 {
277     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
278     if (buflen < 256)
279     return ERR_PTR(-ENOMEM);
280     /* rename_lock is locked/unlocked by dentry_path_raw(). */
281     return dentry_path_raw(dentry, buffer, buflen - 1);
282     #else
283     char *pos = buffer + buflen - 1;
284 kumaneko 211
285 kumaneko 2 if (buflen < 256)
286     return ERR_PTR(-ENOMEM);
287     *pos = '\0';
288     spin_lock(&dcache_lock);
289     while (!IS_ROOT(dentry)) {
290     struct dentry *parent = dentry->d_parent;
291     const char *name = dentry->d_name.name;
292     const int len = dentry->d_name.len;
293 kumaneko 211
294 kumaneko 2 pos -= len;
295     if (pos <= buffer) {
296     pos = ERR_PTR(-ENOMEM);
297     break;
298     }
299     memmove(pos, name, len);
300     *--pos = '/';
301     dentry = parent;
302     }
303     spin_unlock(&dcache_lock);
304     if (pos == buffer + buflen - 1)
305     *--pos = '/';
306     return pos;
307     #endif
308     }
309    
310     /**
311 kumaneko 101 * cs_get_local_path - Get the path of a dentry.
312 kumaneko 2 *
313     * @dentry: Pointer to "struct dentry".
314     * @buffer: Pointer to buffer to return value in.
315     * @buflen: Sizeof @buffer.
316     *
317     * Returns the buffer on success, an error code otherwise.
318     */
319 kumaneko 101 static char *cs_get_local_path(struct dentry *dentry, char * const buffer,
320     const int buflen)
321 kumaneko 2 {
322     struct super_block *sb = dentry->d_sb;
323 kumaneko 101 char *pos = cs_get_dentry_path(dentry, buffer, buflen);
324 kumaneko 211
325 kumaneko 2 if (IS_ERR(pos))
326     return pos;
327     /* Convert from $PID to self if $PID is current thread. */
328     if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
329     char *ep;
330     const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
331 kumaneko 211
332 kumaneko 324 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
333 kumaneko 2 if (*ep == '/' && pid && pid ==
334 kumaneko 326 task_tgid_nr_ns(current, proc_pid_ns(sb))) {
335 kumaneko 324 pos = ep - 5;
336     if (pos < buffer)
337     goto out;
338     memmove(pos, "/self", 5);
339     }
340     #else
341     if (*ep == '/' && pid && pid ==
342 kumaneko 2 task_tgid_nr_ns(current, sb->s_fs_info)) {
343     pos = ep - 5;
344     if (pos < buffer)
345     goto out;
346     memmove(pos, "/self", 5);
347     }
348 kumaneko 324 #endif
349 kumaneko 2 goto prepend_filesystem_name;
350     }
351     /* Use filesystem name for unnamed devices. */
352     if (!MAJOR(sb->s_dev))
353     goto prepend_filesystem_name;
354     {
355 kumaneko 187 struct inode *inode = d_backing_inode(sb->s_root);
356 kumaneko 280
357 kumaneko 2 /*
358     * Use filesystem name if filesystems does not support rename()
359     * operation.
360     */
361 kumaneko 125 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
362 kumaneko 2 if (inode->i_op && !inode->i_op->rename)
363     goto prepend_filesystem_name;
364 kumaneko 198 #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
365 kumaneko 125 if (!inode->i_op->rename && !inode->i_op->rename2)
366     goto prepend_filesystem_name;
367 kumaneko 198 #else
368     if (!inode->i_op->rename)
369     goto prepend_filesystem_name;
370 kumaneko 125 #endif
371 kumaneko 2 }
372     /* Prepend device name. */
373     {
374     char name[64];
375     int name_len;
376     const dev_t dev = sb->s_dev;
377 kumaneko 211
378 kumaneko 2 name[sizeof(name) - 1] = '\0';
379     snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
380     MINOR(dev));
381     name_len = strlen(name);
382     pos -= name_len;
383     if (pos < buffer)
384     goto out;
385     memmove(pos, name, name_len);
386     return pos;
387     }
388     /* Prepend filesystem name. */
389     prepend_filesystem_name:
390     {
391     const char *name = sb->s_type->name;
392     const int name_len = strlen(name);
393 kumaneko 211
394 kumaneko 2 pos -= name_len + 1;
395     if (pos < buffer)
396     goto out;
397     memmove(pos, name, name_len);
398     pos[name_len] = ':';
399     }
400     return pos;
401     out:
402     return ERR_PTR(-ENOMEM);
403     }
404    
405     /**
406 kumaneko 101 * cs_realpath - Returns realpath(3) of the given pathname but ignores chroot'ed root.
407 kumaneko 2 *
408     * @path: Pointer to "struct path".
409     *
410     * Returns the realpath of the given @path on success, NULL otherwise.
411     *
412     * This function uses kzalloc(), so caller must kfree() if this function
413     * didn't return NULL.
414     */
415 kumaneko 139 char *cs_realpath(const struct path *path)
416 kumaneko 2 {
417     char *buf = NULL;
418     char *name = NULL;
419     unsigned int buf_len = PAGE_SIZE / 2;
420     struct dentry *dentry = path->dentry;
421     struct super_block *sb;
422 kumaneko 211
423 kumaneko 2 if (!dentry)
424     return NULL;
425     sb = dentry->d_sb;
426     while (1) {
427     char *pos;
428     struct inode *inode;
429 kumaneko 211
430 kumaneko 2 buf_len <<= 1;
431     kfree(buf);
432     buf = kmalloc(buf_len, GFP_NOFS);
433     if (!buf)
434     break;
435     /* To make sure that pos is '\0' terminated. */
436     buf[buf_len - 1] = '\0';
437 kumaneko 290 /* For "pipe:[\$]" and "socket:[\$]". */
438 kumaneko 2 if (dentry->d_op && dentry->d_op->d_dname) {
439     pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
440     goto encode;
441     }
442 kumaneko 187 inode = d_backing_inode(sb->s_root);
443 kumaneko 2 /*
444 kumaneko 280 * Use local name for "filesystems without rename() operation
445     * and device file" or "path without vfsmount" or "absolute
446     * name is unavailable" cases.
447 kumaneko 2 */
448 kumaneko 125 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
449 kumaneko 280 if (!path->mnt ||
450     (inode->i_op && !inode->i_op->rename &&
451     !(sb->s_type->fs_flags & FS_REQUIRES_DEV)))
452 kumaneko 2 pos = ERR_PTR(-EINVAL);
453     else {
454     /* Get absolute name for the rest. */
455 kumaneko 101 cs_realpath_lock();
456     pos = cs_get_absolute_path(path, buf, buf_len - 1);
457     cs_realpath_unlock();
458 kumaneko 2 }
459 kumaneko 198 #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
460 kumaneko 125 if (!path->mnt ||
461 kumaneko 280 (!inode->i_op->rename && !inode->i_op->rename2 &&
462     !(sb->s_type->fs_flags & FS_REQUIRES_DEV)))
463 kumaneko 186 pos = ERR_PTR(-EINVAL);
464 kumaneko 125 else
465     pos = cs_get_absolute_path(path, buf, buf_len - 1);
466 kumaneko 198 #else
467 kumaneko 280 if (!path->mnt ||
468     (!inode->i_op->rename &&
469     !(sb->s_type->fs_flags & FS_REQUIRES_DEV)))
470 kumaneko 198 pos = ERR_PTR(-EINVAL);
471     else
472     pos = cs_get_absolute_path(path, buf, buf_len - 1);
473 kumaneko 125 #endif
474 kumaneko 186 if (pos == ERR_PTR(-EINVAL))
475     pos = cs_get_local_path(path->dentry, buf,
476     buf_len - 1);
477 kumaneko 2 encode:
478     if (IS_ERR(pos))
479     continue;
480 kumaneko 101 name = cs_encode(pos);
481 kumaneko 2 break;
482     }
483     kfree(buf);
484     if (!name)
485 kumaneko 101 cs_warn_oom(__func__);
486 kumaneko 2 return name;
487     }
488    
489     /**
490 kumaneko 101 * cs_encode2 - Encode binary string to ascii string.
491 kumaneko 2 *
492     * @str: String in binary format. Maybe NULL.
493     * @str_len: Size of @str in byte.
494     *
495     * Returns pointer to @str in ascii format on success, NULL otherwise.
496     *
497     * This function uses kzalloc(), so caller must kfree() if this function
498     * didn't return NULL.
499     */
500 kumaneko 101 char *cs_encode2(const char *str, int str_len)
501 kumaneko 2 {
502     int i;
503     int len;
504     const char *p = str;
505     char *cp;
506     char *cp0;
507 kumaneko 211
508 kumaneko 2 if (!p)
509     return NULL;
510     len = str_len;
511     for (i = 0; i < str_len; i++) {
512     const unsigned char c = p[i];
513 kumaneko 211
514 kumaneko 2 if (!(c > ' ' && c < 127 && c != '\\'))
515     len += 3;
516     }
517     len++;
518     cp = kzalloc(len, GFP_NOFS);
519     if (!cp)
520     return NULL;
521     cp0 = cp;
522     p = str;
523     for (i = 0; i < str_len; i++) {
524     const unsigned char c = p[i];
525 kumaneko 211
526 kumaneko 2 if (c > ' ' && c < 127 && c != '\\') {
527     *cp++ = c;
528     } else {
529     *cp++ = '\\';
530     *cp++ = (c >> 6) + '0';
531     *cp++ = ((c >> 3) & 7) + '0';
532     *cp++ = (c & 7) + '0';
533     }
534     }
535     return cp0;
536     }
537    
538     /**
539 kumaneko 101 * cs_encode - Encode binary string to ascii string.
540 kumaneko 2 *
541     * @str: String in binary format. Maybe NULL.
542     *
543     * Returns pointer to @str in ascii format on success, NULL otherwise.
544     *
545     * This function uses kzalloc(), so caller must kfree() if this function
546     * didn't return NULL.
547     */
548 kumaneko 101 char *cs_encode(const char *str)
549 kumaneko 2 {
550 kumaneko 101 return str ? cs_encode2(str, strlen(str)) : NULL;
551 kumaneko 2 }
552    
553     /**
554 kumaneko 101 * cs_const_part_length - Evaluate the initial length without a pattern in a token.
555 kumaneko 2 *
556     * @filename: The string to evaluate. Maybe NULL.
557     *
558     * Returns the initial length without a pattern in @filename.
559     */
560 kumaneko 101 static int cs_const_part_length(const char *filename)
561 kumaneko 2 {
562     char c;
563     int len = 0;
564 kumaneko 211
565 kumaneko 2 if (!filename)
566     return 0;
567     while (1) {
568     c = *filename++;
569     if (!c)
570     break;
571     if (c != '\\') {
572     len++;
573     continue;
574     }
575     c = *filename++;
576     switch (c) {
577     case '0': /* "\ooo" */
578     case '1':
579     case '2':
580     case '3':
581     c = *filename++;
582 kumaneko 169 if (c < '0' || c > '7')
583     break;
584     c = *filename++;
585     if (c < '0' || c > '7')
586     break;
587     len += 4;
588     continue;
589 kumaneko 2 }
590     break;
591     }
592     return len;
593     }
594    
595     /**
596 kumaneko 101 * cs_fill_path_info - Fill in "struct cs_path_info" members.
597 kumaneko 2 *
598 kumaneko 101 * @ptr: Pointer to "struct cs_path_info" to fill in.
599 kumaneko 2 *
600     * Returns nothing.
601     *
602 kumaneko 101 * The caller sets "struct cs_path_info"->name.
603 kumaneko 2 */
604 kumaneko 101 void cs_fill_path_info(struct cs_path_info *ptr)
605 kumaneko 2 {
606     const char *name = ptr->name;
607     const int len = strlen(name);
608 kumaneko 211
609 kumaneko 2 ptr->total_len = len;
610 kumaneko 101 ptr->const_len = cs_const_part_length(name);
611 kumaneko 196 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
612     ptr->hash = full_name_hash(NULL, name, len);
613     #else
614 kumaneko 2 ptr->hash = full_name_hash(name, len);
615 kumaneko 196 #endif
616 kumaneko 2 }
617    
618     /**
619 kumaneko 101 * cs_get_exe - Get cs_realpath() of current process.
620 kumaneko 2 *
621 kumaneko 101 * Returns the cs_realpath() of current process on success, NULL otherwise.
622 kumaneko 2 *
623     * This function uses kzalloc(), so the caller must kfree()
624     * if this function didn't return NULL.
625     */
626 kumaneko 101 char *cs_get_exe(void)
627 kumaneko 2 {
628     struct mm_struct *mm;
629 kumaneko 139 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
630 kumaneko 2 struct vm_area_struct *vma;
631 kumaneko 56 #endif
632 kumaneko 139 struct file *exe_file;
633 kumaneko 211
634 kumaneko 359 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
635 kumaneko 2 if (current->flags & PF_KTHREAD)
636     return kstrdup("<kernel>", GFP_NOFS);
637 kumaneko 359 #else
638     if (segment_eq(get_fs(), KERNEL_DS))
639     return kstrdup("<kernel>", GFP_NOFS);
640     #endif
641 kumaneko 2 mm = current->mm;
642     if (!mm)
643     goto task_has_no_mm;
644 kumaneko 359 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
645     /* Not using get_mm_exe_file() as it is not exported. */
646     rcu_read_lock();
647     exe_file = rcu_dereference(mm->exe_file);
648 kumaneko 386 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)
649     if (exe_file && !get_file_rcu(&exe_file))
650     exe_file = NULL;
651     #else
652 kumaneko 359 if (exe_file && !get_file_rcu(exe_file))
653     exe_file = NULL;
654 kumaneko 386 #endif
655 kumaneko 359 rcu_read_unlock();
656     #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
657 kumaneko 310 exe_file = get_mm_exe_file(mm);
658     #else
659 kumaneko 2 down_read(&mm->mmap_sem);
660 kumaneko 139 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
661     /* Not using get_mm_exe_file() as it is not exported. */
662     exe_file = mm->exe_file;
663 kumaneko 56 #else
664 kumaneko 139 exe_file = NULL;
665 kumaneko 2 for (vma = mm->mmap; vma; vma = vma->vm_next) {
666     if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
667 kumaneko 139 exe_file = vma->vm_file;
668 kumaneko 2 break;
669     }
670     }
671 kumaneko 56 #endif
672 kumaneko 139 if (exe_file)
673     get_file(exe_file);
674 kumaneko 2 up_read(&mm->mmap_sem);
675 kumaneko 310 #endif
676 kumaneko 139 if (exe_file) {
677     char *cp = cs_realpath(&exe_file->f_path);
678 kumaneko 211
679 kumaneko 139 fput(exe_file);
680 kumaneko 2 return cp;
681 kumaneko 139 }
682 kumaneko 2 task_has_no_mm:
683     /* I'don't know. */
684     return kstrdup("<unknown>", GFP_NOFS);
685     }
686    
687     /**
688 kumaneko 101 * cs_get_exename - Get cs_realpath() of current process.
689 kumaneko 2 *
690 kumaneko 101 * @buf: Pointer to "struct cs_path_info".
691 kumaneko 2 *
692     * Returns true on success, false otherwise.
693     *
694     * This function uses kzalloc(), so the caller must kfree()
695     * if this function returned true.
696     */
697 kumaneko 101 bool cs_get_exename(struct cs_path_info *buf)
698 kumaneko 2 {
699 kumaneko 101 buf->name = cs_get_exe();
700 kumaneko 2 if (buf->name) {
701 kumaneko 101 cs_fill_path_info(buf);
702 kumaneko 2 return true;
703     }
704     return false;
705     }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26