オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Annotation of /trunk/1.7.x/ccs-patch/security/ccsecurity/realpath.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2219 - (hide annotations) (download) (as text)
Tue Mar 3 06:30:38 2009 UTC (15 years, 2 months ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/realpath.c
File MIME type: text/x-csrc
File size: 19618 byte(s)


1 kumaneko 111 /*
2     * fs/realpath.c
3     *
4     * Get the canonicalized absolute pathnames. The basis for SAKURA and TOMOYO.
5     *
6 kumaneko 2030 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 kumaneko 111 *
8 kumaneko 2219 * Version: 1.6.7-rc 2009/03/03
9 kumaneko 111 *
10     * This file is applicable to both 2.4.30 and 2.6.11 and later.
11     * See README.ccs for ChangeLog.
12     *
13     */
14     #include <linux/string.h>
15     #include <linux/mm.h>
16     #include <linux/utime.h>
17     #include <linux/file.h>
18     #include <linux/smp_lock.h>
19     #include <linux/module.h>
20     #include <linux/slab.h>
21     #include <asm/uaccess.h>
22     #include <asm/atomic.h>
23     #include <linux/version.h>
24 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
25 kumaneko 111 #include <linux/namei.h>
26     #include <linux/mount.h>
27 kumaneko 2002 static const int ccs_lookup_flags = LOOKUP_FOLLOW;
28 kumaneko 111 #else
29 kumaneko 2002 static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
30 kumaneko 111 #endif
31     #include <linux/realpath.h>
32     #include <linux/proc_fs.h>
33     #include <linux/ccs_common.h>
34    
35 kumaneko 1052 /**
36 kumaneko 2002 * ccs_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
37 kumaneko 111 *
38 kumaneko 1052 * @dentry: Pointer to "struct dentry".
39     * @vfsmnt: Pointer to "struct vfsmount".
40     * @buffer: Pointer to buffer to return value in.
41     * @buflen: Sizeof @buffer.
42     *
43     * Returns 0 on success, -ENOMEM otherwise.
44     *
45 kumaneko 1064 * Caller holds the dcache_lock and vfsmount_lock.
46 kumaneko 111 * Based on __d_path() in fs/dcache.c
47     *
48     * If dentry is a directory, trailing '/' is appended.
49 kumaneko 1052 * Characters out of 0x20 < c < 0x7F range are converted to
50     * \ooo style octal string.
51 kumaneko 111 * Character \ is converted to \\ string.
52     */
53 kumaneko 2002 static int ccs_get_absolute_path(struct dentry *dentry, struct vfsmount *vfsmnt,
54     char *buffer, int buflen)
55 kumaneko 111 {
56 kumaneko 1052 /***** CRITICAL SECTION START *****/
57 kumaneko 111 char *start = buffer;
58     char *end = buffer + buflen;
59 kumaneko 621 bool is_dir = (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode));
60 kumaneko 111
61 kumaneko 1052 if (buflen < 256)
62     goto out;
63 kumaneko 111
64     *--end = '\0';
65     buflen--;
66    
67     for (;;) {
68     struct dentry *parent;
69    
70     if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
71     /* Global root? */
72 kumaneko 1052 if (vfsmnt->mnt_parent == vfsmnt)
73 kumaneko 111 break;
74     dentry = vfsmnt->mnt_mountpoint;
75     vfsmnt = vfsmnt->mnt_parent;
76     continue;
77     }
78     if (is_dir) {
79 kumaneko 1052 is_dir = false;
80     *--end = '/';
81     buflen--;
82 kumaneko 111 }
83     parent = dentry->d_parent;
84     {
85     const char *sp = dentry->d_name.name;
86     const char *cp = sp + dentry->d_name.len - 1;
87     unsigned char c;
88    
89 kumaneko 1052 /*
90     * Exception: Use /proc/self/ rather than
91     * /proc/\$/ for current process.
92     */
93     if (IS_ROOT(parent) && *sp > '0' && *sp <= '9' &&
94     parent->d_sb &&
95     parent->d_sb->s_magic == PROC_SUPER_MAGIC) {
96 kumaneko 111 char *ep;
97 kumaneko 1052 const pid_t pid
98     = (pid_t) simple_strtoul(sp, &ep, 10);
99 kumaneko 1778 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
100     const pid_t tgid
101     = task_tgid_nr_ns(current,
102     dentry->d_sb->
103     s_fs_info);
104     if (!*ep && pid == tgid && tgid) {
105 kumaneko 1052 sp = "self";
106     cp = sp + 3;
107     }
108 kumaneko 111 #else
109 kumaneko 1778 if (!*ep && pid == sys_getpid()) {
110 kumaneko 1052 sp = "self";
111     cp = sp + 3;
112     }
113 kumaneko 111 #endif
114     }
115    
116     while (sp <= cp) {
117 kumaneko 1052 c = *(unsigned char *) cp;
118 kumaneko 111 if (c == '\\') {
119     buflen -= 2;
120 kumaneko 1052 if (buflen < 0)
121     goto out;
122 kumaneko 111 *--end = '\\';
123     *--end = '\\';
124     } else if (c > ' ' && c < 127) {
125 kumaneko 1052 if (--buflen < 0)
126     goto out;
127 kumaneko 111 *--end = (char) c;
128     } else {
129     buflen -= 4;
130 kumaneko 1052 if (buflen < 0)
131     goto out;
132 kumaneko 111 *--end = (c & 7) + '0';
133     *--end = ((c >> 3) & 7) + '0';
134     *--end = (c >> 6) + '0';
135     *--end = '\\';
136     }
137     cp--;
138     }
139 kumaneko 1052 if (--buflen < 0)
140     goto out;
141 kumaneko 111 *--end = '/';
142     }
143     dentry = parent;
144     }
145 kumaneko 1052 if (*end == '/') {
146     buflen++;
147     end++;
148     }
149 kumaneko 111 {
150     const char *sp = dentry->d_name.name;
151     const char *cp = sp + dentry->d_name.len - 1;
152     unsigned char c;
153     while (sp <= cp) {
154 kumaneko 1052 c = *(unsigned char *) cp;
155 kumaneko 111 if (c == '\\') {
156     buflen -= 2;
157 kumaneko 1052 if (buflen < 0)
158     goto out;
159 kumaneko 111 *--end = '\\';
160     *--end = '\\';
161     } else if (c > ' ' && c < 127) {
162 kumaneko 1052 if (--buflen < 0)
163     goto out;
164 kumaneko 111 *--end = (char) c;
165     } else {
166     buflen -= 4;
167 kumaneko 1052 if (buflen < 0)
168     goto out;
169 kumaneko 111 *--end = (c & 7) + '0';
170     *--end = ((c >> 3) & 7) + '0';
171     *--end = (c >> 6) + '0';
172     *--end = '\\';
173     }
174     cp--;
175     }
176     }
177     /* Move the pathname to the top of the buffer. */
178     memmove(start, end, strlen(end) + 1);
179     return 0;
180     out:
181     return -ENOMEM;
182 kumaneko 1052 /***** CRITICAL SECTION END *****/
183 kumaneko 111 }
184    
185 kumaneko 1052 /**
186 kumaneko 1054 * ccs_realpath_from_dentry2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
187 kumaneko 1052 *
188     * @dentry: Pointer to "struct dentry".
189     * @mnt: Pointer to "struct vfsmount".
190     * @newname: Pointer to buffer to return value in.
191 kumaneko 1064 * @newname_len: Size of @newname.
192 kumaneko 1052 *
193     * Returns 0 on success, negative value otherwise.
194     */
195     int ccs_realpath_from_dentry2(struct dentry *dentry, struct vfsmount *mnt,
196     char *newname, int newname_len)
197 kumaneko 111 {
198 kumaneko 1379 int error = -EINVAL;
199 kumaneko 111 struct dentry *d_dentry;
200     struct vfsmount *d_mnt;
201 kumaneko 1379 if (!dentry || !newname || newname_len <= 2048)
202     goto out;
203 kumaneko 1259 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
204     if (dentry->d_op && dentry->d_op->d_dname) {
205     /* For "socket:[\$]" and "pipe:[\$]". */
206     static const int offset = 1536;
207     char *dp = newname;
208     char *sp = dentry->d_op->d_dname(dentry, newname + offset,
209     newname_len - offset);
210     if (IS_ERR(sp)) {
211     error = PTR_ERR(sp);
212     goto out;
213     }
214     error = -ENOMEM;
215     newname += offset;
216     while (1) {
217     const unsigned char c = *(unsigned char *) sp++;
218     if (c == '\\') {
219     if (dp + 2 >= newname)
220     break;
221     *dp++ = '\\';
222     *dp++ = '\\';
223     } else if (c > ' ' && c < 127) {
224     if (dp + 1 >= newname)
225     break;
226     *dp++ = (char) c;
227     } else if (c) {
228     if (dp + 4 >= newname)
229     break;
230     *dp++ = '\\';
231     *dp++ = (c >> 6) + '0';
232     *dp++ = ((c >> 3) & 7) + '0';
233     *dp++ = (c & 7) + '0';
234     } else {
235     *dp = '\0';
236     return 0;
237     }
238     }
239     goto out;
240     }
241     #endif
242 kumaneko 1379 if (!mnt)
243     goto out;
244 kumaneko 111 d_dentry = dget(dentry);
245     d_mnt = mntget(mnt);
246     /***** CRITICAL SECTION START *****/
247 kumaneko 1474 ccs_realpath_lock();
248 kumaneko 2002 error = ccs_get_absolute_path(d_dentry, d_mnt, newname, newname_len);
249 kumaneko 1474 ccs_realpath_unlock();
250 kumaneko 111 /***** CRITICAL SECTION END *****/
251     dput(d_dentry);
252     mntput(d_mnt);
253 kumaneko 1259 out:
254 kumaneko 1056 if (error)
255 kumaneko 1379 printk(KERN_WARNING "ccs_realpath: Pathname too long. (%d)\n",
256     error);
257 kumaneko 111 return error;
258     }
259    
260 kumaneko 1052 /**
261 kumaneko 1054 * ccs_realpath_from_dentry - Returns realpath(3) of the given pathname but ignores chroot'ed root.
262 kumaneko 1052 *
263     * @dentry: Pointer to "struct dentry".
264     * @mnt: Pointer to "struct vfsmount".
265     *
266     * Returns the realpath of the given @dentry and @mnt on success,
267     * NULL otherwise.
268     *
269     * These functions use ccs_alloc(), so caller must ccs_free()
270     * if these functions didn't return NULL.
271     */
272     char *ccs_realpath_from_dentry(struct dentry *dentry, struct vfsmount *mnt)
273 kumaneko 111 {
274 kumaneko 2037 char *buf = ccs_alloc(CCS_MAX_PATHNAME_LEN, false);
275 kumaneko 1052 if (buf && ccs_realpath_from_dentry2(dentry, mnt, buf,
276     CCS_MAX_PATHNAME_LEN - 1) == 0)
277     return buf;
278 kumaneko 111 ccs_free(buf);
279     return NULL;
280     }
281    
282 kumaneko 1052 /**
283     * ccs_realpath - Get realpath of a pathname.
284     *
285     * @pathname: The pathname to solve.
286     *
287     * Returns the realpath of @pathname on success, NULL otherwise.
288     */
289     char *ccs_realpath(const char *pathname)
290 kumaneko 111 {
291     struct nameidata nd;
292 kumaneko 2002 if (pathname && path_lookup(pathname, ccs_lookup_flags, &nd) == 0) {
293 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
294     char *buf = ccs_realpath_from_dentry(nd.path.dentry,
295     nd.path.mnt);
296 kumaneko 990 path_put(&nd.path);
297     #else
298 kumaneko 1052 char *buf = ccs_realpath_from_dentry(nd.dentry, nd.mnt);
299 kumaneko 111 path_release(&nd);
300 kumaneko 990 #endif
301 kumaneko 111 return buf;
302     }
303     return NULL;
304     }
305    
306 kumaneko 1052 /**
307 kumaneko 2037 * ccs_realpath_both - Get realpath of a pathname and symlink.
308 kumaneko 1052 *
309     * @pathname: The pathname to solve.
310 kumaneko 2037 * @ee: Pointer to "struct ccs_execve_entry".
311 kumaneko 1052 *
312 kumaneko 2075 * Returns 0 on success, negative value otherwise.
313 kumaneko 1052 */
314 kumaneko 2075 int ccs_realpath_both(const char *pathname, struct ccs_execve_entry *ee)
315 kumaneko 111 {
316     struct nameidata nd;
317 kumaneko 2037 int ret;
318     bool is_symlink;
319     if (!pathname ||
320     path_lookup(pathname, ccs_lookup_flags ^ LOOKUP_FOLLOW, &nd))
321 kumaneko 2075 return -ENOENT;
322 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
323 kumaneko 2037 is_symlink = nd.path.dentry->d_inode &&
324     S_ISLNK(nd.path.dentry->d_inode->i_mode);
325     ret = ccs_realpath_from_dentry2(nd.path.dentry, nd.path.mnt,
326     ee->tmp, CCS_EXEC_TMPSIZE - 1);
327     path_put(&nd.path);
328 kumaneko 990 #else
329 kumaneko 2037 is_symlink = nd.dentry->d_inode && S_ISLNK(nd.dentry->d_inode->i_mode);
330     ret = ccs_realpath_from_dentry2(nd.dentry, nd.mnt, ee->tmp,
331     CCS_EXEC_TMPSIZE - 1);
332     path_release(&nd);
333 kumaneko 990 #endif
334 kumaneko 2037 if (ret)
335 kumaneko 2075 return -ENOMEM;
336 kumaneko 2044 if (strlen(ee->tmp) > CCS_MAX_PATHNAME_LEN - 1)
337 kumaneko 2075 return -ENOMEM;
338 kumaneko 2037 ee->program_path[CCS_MAX_PATHNAME_LEN - 1] = '\0';
339     if (!is_symlink) {
340     strncpy(ee->program_path, ee->tmp,
341     CCS_MAX_PATHNAME_LEN - 1);
342 kumaneko 2075 return 0;
343 kumaneko 111 }
344 kumaneko 2037 if (path_lookup(pathname, ccs_lookup_flags, &nd))
345 kumaneko 2075 return -ENOENT;
346 kumaneko 2037 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
347     ret = ccs_realpath_from_dentry2(nd.path.dentry, nd.path.mnt,
348     ee->program_path,
349     CCS_MAX_PATHNAME_LEN - 1);
350     path_put(&nd.path);
351     #else
352     ret = ccs_realpath_from_dentry2(nd.dentry, nd.mnt, ee->program_path,
353     CCS_MAX_PATHNAME_LEN - 1);
354     path_release(&nd);
355     #endif
356 kumaneko 2075 return ret ? -ENOMEM : 0;
357 kumaneko 111 }
358    
359 kumaneko 1052 /**
360 kumaneko 2002 * ccs_round_up - Round up an integer so that the returned pointers are appropriately aligned.
361 kumaneko 1052 *
362     * @size: Size in bytes.
363     *
364     * Returns rounded value of @size.
365     *
366     * FIXME: Are there more requirements that is needed for assigning value
367     * atomically?
368 kumaneko 111 */
369 kumaneko 2002 static inline unsigned int ccs_round_up(const unsigned int size)
370 kumaneko 1052 {
371     if (sizeof(void *) >= sizeof(long))
372     return ((size + sizeof(void *) - 1)
373     / sizeof(void *)) * sizeof(void *);
374     else
375     return ((size + sizeof(long) - 1)
376     / sizeof(long)) * sizeof(long);
377 kumaneko 111 }
378    
379 kumaneko 2002 static unsigned int ccs_allocated_memory_for_elements;
380     static unsigned int ccs_quota_for_elements;
381 kumaneko 111
382 kumaneko 1052 /**
383     * ccs_alloc_element - Allocate permanent memory for structures.
384     *
385     * @size: Size in bytes.
386     *
387     * Returns pointer to allocated memory on success, NULL otherwise.
388     *
389     * The RAM is chunked, so NEVER try to kfree() the returned pointer.
390     */
391     void *ccs_alloc_element(const unsigned int size)
392 kumaneko 111 {
393 kumaneko 652 static DEFINE_MUTEX(lock);
394 kumaneko 2002 static char *ccs_buf;
395     static unsigned int ccs_buf_used_len = PAGE_SIZE;
396 kumaneko 111 char *ptr = NULL;
397 kumaneko 2002 const unsigned int word_aligned_size = ccs_round_up(size);
398 kumaneko 1052 if (word_aligned_size > PAGE_SIZE)
399     return NULL;
400 kumaneko 652 mutex_lock(&lock);
401 kumaneko 2002 if (ccs_buf_used_len + word_aligned_size > PAGE_SIZE) {
402     if (!ccs_quota_for_elements || ccs_allocated_memory_for_elements
403     + PAGE_SIZE <= ccs_quota_for_elements)
404 kumaneko 1180 ptr = kzalloc(PAGE_SIZE, GFP_KERNEL);
405 kumaneko 1052 if (!ptr) {
406     printk(KERN_WARNING "ERROR: Out of memory "
407     "for ccs_alloc_element().\n");
408 kumaneko 2040 if (!ccs_policy_loaded)
409 kumaneko 1052 panic("MAC Initialization failed.\n");
410 kumaneko 111 } else {
411 kumaneko 2002 ccs_buf = ptr;
412     ccs_allocated_memory_for_elements += PAGE_SIZE;
413     ccs_buf_used_len = word_aligned_size;
414 kumaneko 111 }
415     } else if (word_aligned_size) {
416     int i;
417 kumaneko 2002 ptr = ccs_buf + ccs_buf_used_len;
418     ccs_buf_used_len += word_aligned_size;
419 kumaneko 111 for (i = 0; i < word_aligned_size; i++) {
420 kumaneko 1052 if (!ptr[i])
421     continue;
422     printk(KERN_ERR "WARNING: Reserved memory was tainted! "
423     "The system might go wrong.\n");
424     ptr[i] = '\0';
425 kumaneko 111 }
426     }
427 kumaneko 652 mutex_unlock(&lock);
428 kumaneko 111 return ptr;
429     }
430    
431 kumaneko 2002 static unsigned int ccs_allocated_memory_for_savename;
432     static unsigned int ccs_quota_for_savename;
433 kumaneko 111
434     #define MAX_HASH 256
435    
436 kumaneko 1052 /* Structure for string data. */
437 kumaneko 2002 struct ccs_name_entry {
438 kumaneko 731 struct list1_head list;
439 kumaneko 2002 struct ccs_path_info entry;
440 kumaneko 214 };
441 kumaneko 111
442 kumaneko 1052 /* Structure for available memory region. */
443 kumaneko 2002 struct ccs_free_memory_block_list {
444 kumaneko 731 struct list_head list;
445 kumaneko 1052 char *ptr; /* Pointer to a free area. */
446     int len; /* Length of the area. */
447 kumaneko 214 };
448 kumaneko 111
449 kumaneko 2002 /* The list for "struct ccs_name_entry". */
450     static struct list1_head ccs_name_list[MAX_HASH];
451 kumaneko 731
452 kumaneko 1052 /**
453     * ccs_save_name - Allocate permanent memory for string data.
454     *
455     * @name: The string to store into the permernent memory.
456     *
457 kumaneko 2002 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
458 kumaneko 1052 *
459     * The RAM is shared, so NEVER try to modify or kfree() the returned name.
460     */
461 kumaneko 2002 const struct ccs_path_info *ccs_save_name(const char *name)
462 kumaneko 111 {
463 kumaneko 2002 static LIST_HEAD(ccs_fmb_list);
464 kumaneko 652 static DEFINE_MUTEX(lock);
465 kumaneko 2002 struct ccs_name_entry *ptr;
466 kumaneko 111 unsigned int hash;
467 kumaneko 2002 struct ccs_free_memory_block_list *fmb;
468 kumaneko 111 int len;
469 kumaneko 731 char *cp;
470 kumaneko 1052 if (!name)
471     return NULL;
472 kumaneko 111 len = strlen(name) + 1;
473     if (len > CCS_MAX_PATHNAME_LEN) {
474 kumaneko 1052 printk(KERN_WARNING "ERROR: Name too long "
475     "for ccs_save_name().\n");
476 kumaneko 111 return NULL;
477     }
478     hash = full_name_hash((const unsigned char *) name, len - 1);
479 kumaneko 652 mutex_lock(&lock);
480 kumaneko 2002 list1_for_each_entry(ptr, &ccs_name_list[hash % MAX_HASH], list) {
481 kumaneko 1052 if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
482     goto out;
483 kumaneko 111 }
484 kumaneko 2002 list_for_each_entry(fmb, &ccs_fmb_list, list) {
485 kumaneko 1052 if (len <= fmb->len)
486     goto ready;
487 kumaneko 111 }
488 kumaneko 2002 if (!ccs_quota_for_savename ||
489     ccs_allocated_memory_for_savename + PAGE_SIZE
490     <= ccs_quota_for_savename)
491 kumaneko 1180 cp = kzalloc(PAGE_SIZE, GFP_KERNEL);
492     else
493     cp = NULL;
494 kumaneko 1016 fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
495 kumaneko 731 if (!cp || !fmb) {
496     kfree(cp);
497     kfree(fmb);
498 kumaneko 1052 printk(KERN_WARNING "ERROR: Out of memory "
499     "for ccs_save_name().\n");
500 kumaneko 2040 if (!ccs_policy_loaded)
501 kumaneko 1052 panic("MAC Initialization failed.\n");
502 kumaneko 731 ptr = NULL;
503     goto out;
504     }
505 kumaneko 2002 ccs_allocated_memory_for_savename += PAGE_SIZE;
506     list_add(&fmb->list, &ccs_fmb_list);
507 kumaneko 731 fmb->ptr = cp;
508     fmb->len = PAGE_SIZE;
509     ready:
510 kumaneko 1052 ptr = ccs_alloc_element(sizeof(*ptr));
511     if (!ptr)
512     goto out;
513 kumaneko 111 ptr->entry.name = fmb->ptr;
514     memmove(fmb->ptr, name, len);
515 kumaneko 1052 ccs_fill_path_info(&ptr->entry);
516 kumaneko 111 fmb->ptr += len;
517     fmb->len -= len;
518 kumaneko 2002 list1_add_tail_mb(&ptr->list, &ccs_name_list[hash % MAX_HASH]);
519 kumaneko 111 if (fmb->len == 0) {
520 kumaneko 731 list_del(&fmb->list);
521     kfree(fmb);
522 kumaneko 111 }
523     out:
524 kumaneko 652 mutex_unlock(&lock);
525 kumaneko 111 return ptr ? &ptr->entry : NULL;
526     }
527    
528 kumaneko 1052 /* Structure for temporarily allocated memory. */
529 kumaneko 2002 struct ccs_cache_entry {
530 kumaneko 111 struct list_head list;
531     void *ptr;
532     int size;
533 kumaneko 214 };
534 kumaneko 111
535 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
536     static struct kmem_cache *ccs_cachep;
537 kumaneko 111 #else
538 kumaneko 1052 static kmem_cache_t *ccs_cachep;
539 kumaneko 111 #endif
540    
541 kumaneko 1052 /**
542     * ccs_realpath_init - Initialize realpath related code.
543     *
544     * Returns 0.
545     */
546     static int __init ccs_realpath_init(void)
547 kumaneko 111 {
548 kumaneko 731 int i;
549 kumaneko 2037 /* Constraint for ccs_save_name(). */
550 kumaneko 1052 if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
551     panic("Bad size.");
552 kumaneko 2037 /* Constraint for "struct ccs_execve_entry"->tmp users. */
553     if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)
554     panic("Bad size.");
555 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
556 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
557     sizeof(struct ccs_cache_entry),
558 kumaneko 1052 0, 0, NULL);
559 kumaneko 316 #else
560 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
561     sizeof(struct ccs_cache_entry),
562 kumaneko 1052 0, 0, NULL, NULL);
563 kumaneko 316 #endif
564 kumaneko 1052 if (!ccs_cachep)
565     panic("Can't create cache.\n");
566     for (i = 0; i < MAX_HASH; i++)
567 kumaneko 2002 INIT_LIST1_HEAD(&ccs_name_list[i]);
568 kumaneko 722 INIT_LIST1_HEAD(&KERNEL_DOMAIN.acl_info_list);
569 kumaneko 1052 KERNEL_DOMAIN.domainname = ccs_save_name(ROOT_NAME);
570 kumaneko 2002 list1_add_tail_mb(&KERNEL_DOMAIN.list, &ccs_domain_list);
571 kumaneko 1052 if (ccs_find_domain(ROOT_NAME) != &KERNEL_DOMAIN)
572     panic("Can't register KERNEL_DOMAIN");
573     return 0;
574 kumaneko 111 }
575    
576 kumaneko 1084 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
577 kumaneko 1052 __initcall(ccs_realpath_init);
578 kumaneko 1084 #else
579 kumaneko 1106 core_initcall(ccs_realpath_init);
580 kumaneko 1084 #endif
581 kumaneko 1052
582 kumaneko 2002 /* The list for "struct ccs_cache_entry". */
583     static LIST_HEAD(ccs_audit_cache_list);
584     static LIST_HEAD(ccs_acl_cache_list);
585     static DEFINE_SPINLOCK(ccs_cache_list_lock);
586 kumaneko 1052
587 kumaneko 2002 static unsigned int ccs_dynamic_memory_size;
588     static unsigned int ccs_quota_for_dynamic;
589 kumaneko 1052
590     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
591     /**
592 kumaneko 2002 * ccs_round2 - Rounded up to power-of-two value.
593 kumaneko 1052 *
594     * @size: Size in bytes.
595     *
596     * Returns power-of-two of @size.
597     */
598 kumaneko 2002 static int ccs_round2(size_t size)
599 kumaneko 581 {
600     #if PAGE_SIZE == 4096
601     size_t bsize = 32;
602     #else
603     size_t bsize = 64;
604     #endif
605 kumaneko 1064 while (size > bsize)
606     bsize <<= 1;
607 kumaneko 581 return bsize;
608     }
609     #endif
610    
611 kumaneko 1052 /**
612 kumaneko 1793 * ccs_alloc - Allocate memory for temporary purpose.
613 kumaneko 1052 *
614     * @size: Size in bytes.
615     *
616     * Returns pointer to allocated memory on success, NULL otherwise.
617     */
618 kumaneko 1907 void *ccs_alloc(const size_t size, const _Bool check_quota)
619 kumaneko 111 {
620 kumaneko 2002 struct ccs_cache_entry *new_entry;
621 kumaneko 1055 void *ret = kzalloc(size, GFP_KERNEL);
622 kumaneko 1052 if (!ret)
623     goto out;
624 kumaneko 1031 new_entry = kmem_cache_alloc(ccs_cachep, GFP_KERNEL);
625     if (!new_entry) {
626 kumaneko 1064 kfree(ret);
627     ret = NULL;
628 kumaneko 1031 goto out;
629     }
630     INIT_LIST_HEAD(&new_entry->list);
631     new_entry->ptr = ret;
632 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
633 kumaneko 1031 new_entry->size = ksize(ret);
634     #else
635 kumaneko 2002 new_entry->size = ccs_round2(size);
636 kumaneko 1031 #endif
637 kumaneko 1903 if (check_quota) {
638     bool quota_exceeded = false;
639     /***** CRITICAL SECTION START *****/
640 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
641     if (!ccs_quota_for_dynamic ||
642     ccs_dynamic_memory_size + new_entry->size
643     <= ccs_quota_for_dynamic) {
644     list_add_tail(&new_entry->list, &ccs_audit_cache_list);
645     ccs_dynamic_memory_size += new_entry->size;
646 kumaneko 1903 } else {
647     quota_exceeded = true;
648     }
649 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
650 kumaneko 1903 /***** CRITICAL SECTION END *****/
651     if (quota_exceeded) {
652     kfree(ret);
653     kmem_cache_free(ccs_cachep, new_entry);
654     ret = NULL;
655     }
656     } else {
657     /***** CRITICAL SECTION START *****/
658 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
659     list_add(&new_entry->list, &ccs_acl_cache_list);
660     ccs_dynamic_memory_size += new_entry->size;
661     spin_unlock(&ccs_cache_list_lock);
662 kumaneko 1903 /***** CRITICAL SECTION END *****/
663     }
664 kumaneko 1031 out:
665 kumaneko 214 return ret;
666 kumaneko 111 }
667    
668 kumaneko 1052 /**
669     * ccs_free - Release memory allocated by ccs_alloc().
670     *
671     * @p: Pointer returned by ccs_alloc(). May be NULL.
672     *
673     * Returns nothing.
674     */
675 kumaneko 111 void ccs_free(const void *p)
676     {
677     struct list_head *v;
678 kumaneko 2002 struct ccs_cache_entry *entry = NULL;
679 kumaneko 1052 if (!p)
680     return;
681     /***** CRITICAL SECTION START *****/
682 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
683     list_for_each(v, &ccs_acl_cache_list) {
684     entry = list_entry(v, struct ccs_cache_entry, list);
685 kumaneko 1903 if (entry->ptr == p)
686     break;
687     entry = NULL;
688     }
689     if (!entry) {
690 kumaneko 2002 list_for_each(v, &ccs_audit_cache_list) {
691     entry = list_entry(v, struct ccs_cache_entry, list);
692 kumaneko 1903 if (entry->ptr == p)
693     break;
694 kumaneko 1064 entry = NULL;
695 kumaneko 111 }
696 kumaneko 1903 }
697     if (entry) {
698 kumaneko 111 list_del(&entry->list);
699 kumaneko 2002 ccs_dynamic_memory_size -= entry->size;
700 kumaneko 111 }
701 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
702 kumaneko 1052 /***** CRITICAL SECTION END *****/
703 kumaneko 111 if (entry) {
704     kfree(p);
705     kmem_cache_free(ccs_cachep, entry);
706     } else {
707 kumaneko 1052 printk(KERN_WARNING "BUG: ccs_free() with invalid pointer.\n");
708 kumaneko 111 }
709     }
710 kumaneko 1180
711     /**
712     * ccs_read_memory_counter - Check for memory usage.
713     *
714     * @head: Pointer to "struct ccs_io_buffer".
715     *
716     * Returns memory usage.
717     */
718     int ccs_read_memory_counter(struct ccs_io_buffer *head)
719     {
720     if (!head->read_eof) {
721 kumaneko 2002 const unsigned int shared = ccs_allocated_memory_for_savename;
722     const unsigned int private = ccs_allocated_memory_for_elements;
723     const unsigned int dynamic = ccs_dynamic_memory_size;
724 kumaneko 1180 char buffer[64];
725     memset(buffer, 0, sizeof(buffer));
726 kumaneko 2002 if (ccs_quota_for_savename)
727 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
728 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_savename);
729 kumaneko 1180 else
730     buffer[0] = '\0';
731     ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer);
732 kumaneko 2002 if (ccs_quota_for_elements)
733 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
734 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_elements);
735 kumaneko 1180 else
736     buffer[0] = '\0';
737     ccs_io_printf(head, "Private: %10u%s\n", private, buffer);
738 kumaneko 2002 if (ccs_quota_for_dynamic)
739 kumaneko 1903 snprintf(buffer, sizeof(buffer) - 1,
740 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_dynamic);
741 kumaneko 1903 else
742     buffer[0] = '\0';
743     ccs_io_printf(head, "Dynamic: %10u%s\n", dynamic, buffer);
744 kumaneko 1180 ccs_io_printf(head, "Total: %10u\n",
745     shared + private + dynamic);
746     head->read_eof = true;
747     }
748     return 0;
749     }
750    
751     /**
752     * ccs_write_memory_quota - Set memory quota.
753     *
754     * @head: Pointer to "struct ccs_io_buffer".
755     *
756     * Returns 0.
757     */
758     int ccs_write_memory_quota(struct ccs_io_buffer *head)
759     {
760     char *data = head->write_buf;
761     unsigned int size;
762     if (sscanf(data, "Shared: %u", &size) == 1)
763 kumaneko 2002 ccs_quota_for_savename = size;
764 kumaneko 1180 else if (sscanf(data, "Private: %u", &size) == 1)
765 kumaneko 2002 ccs_quota_for_elements = size;
766 kumaneko 1903 else if (sscanf(data, "Dynamic: %u", &size) == 1)
767 kumaneko 2002 ccs_quota_for_dynamic = size;
768 kumaneko 1180 return 0;
769     }

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