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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/fs/ccsecurity/umount.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2854 - (show annotations) (download) (as text)
Wed Aug 5 11:57:20 2009 UTC (14 years, 10 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 4910 byte(s)


1 /*
2 * fs/ccsecurity/umount.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 *
6 * Version: 1.7.0-pre 2009/07/03
7 *
8 * This file is applicable to both 2.4.30 and 2.6.11 and later.
9 * See README.ccs for ChangeLog.
10 *
11 */
12
13 #include <linux/slab.h>
14 #include <linux/version.h>
15 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
16 #include <linux/mount.h>
17 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
18 #include <linux/namespace.h>
19 #endif
20 #include "internal.h"
21 #include <linux/ccsecurity.h>
22
23 /**
24 * ccs_audit_umount_log - Audit unmount log.
25 *
26 * @r: Pointer to "struct ccs_request_info".
27 * @dir: Mount point.
28 * @is_granted: True if this is a granted log.
29 *
30 * Returns 0 on success, negative value otherwise.
31 */
32 static int ccs_audit_umount_log(struct ccs_request_info *r,
33 const char *dir, const bool is_granted)
34 {
35 if (!is_granted && ccs_verbose_mode(r->domain))
36 printk(KERN_WARNING "SAKURA-%s: umount %s denied for %s\n",
37 ccs_get_msg(r->mode == 3), dir,
38 ccs_get_last_name(r->domain));
39 return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_UNMOUNT
40 "%s\n", dir);
41 }
42
43 /**
44 * ccs_update_umount_acl - Update "struct ccs_umount_acl_record" list.
45 *
46 * @dir: The name of directrory.
47 * @is_delete: True if it is a delete request.
48 *
49 * Returns 0 on success, negative value otherwise.
50 */
51 static int ccs_update_umount_acl(const char *dir,
52 struct ccs_domain_info *domain,
53 struct ccs_condition *condition,
54 const bool is_delete)
55 {
56 struct ccs_umount_acl_record *entry = NULL;
57 struct ccs_acl_info *ptr;
58 const struct ccs_path_info *saved_dir;
59 int error = is_delete ? -ENOENT : -ENOMEM;
60 if (!ccs_is_correct_path(dir, 1, 0, 1))
61 return -EINVAL;
62 saved_dir = ccs_get_name(dir);
63 if (!saved_dir)
64 return -ENOMEM;
65 if (!is_delete)
66 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
67 mutex_lock(&ccs_policy_lock);
68 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
69 struct ccs_umount_acl_record *acl;
70 if (ccs_acl_type1(ptr) != TYPE_UMOUNT_ACL)
71 continue;
72 if (ptr->cond != condition)
73 continue;
74 acl = container_of(ptr, struct ccs_umount_acl_record, head);
75 if (acl->dir != saved_dir)
76 continue;
77 if (is_delete)
78 error = ccs_del_domain_acl(ptr);
79 else
80 error = ccs_add_domain_acl(NULL, ptr);
81 break;
82 }
83 if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
84 entry->head.type = TYPE_UMOUNT_ACL;
85 entry->head.cond = condition;
86 entry->dir = saved_dir;
87 saved_dir = NULL;
88 error = ccs_add_domain_acl(domain, &entry->head);
89 entry = NULL;
90 }
91 mutex_unlock(&ccs_policy_lock);
92 ccs_put_name(saved_dir);
93 kfree(entry);
94 return error;
95 }
96
97 /**
98 * ccs_may_umount2 - Check permission for unmount.
99 *
100 * @mnt: Pointer to "struct vfsmount".
101 *
102 * Returns 0 on success, negative value otherwise.
103 *
104 * Caller holds ccs_read_lock().
105 */
106 static int ccs_may_umount2(struct vfsmount *mnt)
107 {
108 struct ccs_request_info r;
109 int error;
110 const char *dir0;
111 bool is_enforce;
112 struct ccs_acl_info *ptr;
113 struct ccs_path_info dir;
114 ccs_check_read_lock();
115 if (!ccs_can_sleep())
116 return 0;
117 ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NAMESPACE);
118 is_enforce = (r.mode == 3);
119 if (!r.mode)
120 return 0;
121 retry:
122 error = -EPERM;
123 dir0 = ccs_realpath_from_dentry(mnt->mnt_root, mnt);
124 if (!dir0)
125 goto out;
126 dir.name = dir0;
127 ccs_fill_path_info(&dir);
128 list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) {
129 struct ccs_umount_acl_record *acl;
130 if (ccs_acl_type2(ptr) != TYPE_UMOUNT_ACL)
131 continue;
132 acl = container_of(ptr, struct ccs_umount_acl_record, head);
133 if (!ccs_path_matches_pattern(&dir, acl->dir) ||
134 !ccs_check_condition(&r, ptr))
135 continue;
136 r.cond = ptr->cond;
137 error = 0;
138 break;
139 }
140 ccs_audit_umount_log(&r, dir0, !error);
141 if (!error)
142 goto out;
143 if (is_enforce)
144 error = ccs_check_supervisor(&r, KEYWORD_ALLOW_UNMOUNT "%s",
145 dir0);
146 else if (ccs_domain_quota_ok(&r))
147 ccs_update_umount_acl(dir0, r.domain, NULL, false);
148 out:
149 kfree(dir0);
150 if (!is_enforce)
151 error = 0;
152 if (error == 1)
153 goto retry;
154 return error;
155 }
156
157 /**
158 * ccs_may_umount - Check permission for unmount.
159 *
160 * @mnt: Pointer to "struct vfsmount".
161 *
162 * Returns 0 on success, negative value otherwise.
163 */
164 int ccs_may_umount(struct vfsmount *mnt)
165 {
166 const int idx = ccs_read_lock();
167 const int error = ccs_may_umount2(mnt);
168 ccs_read_unlock(idx);
169 return error;
170 }
171
172 /**
173 * ccs_write_umount_policy - Write "struct ccs_umount_acl_record" list.
174 *
175 * @data: String to parse.
176 * @domain: Pointer to "struct ccs_domain_info".
177 * @condition: Pointer to "struct ccs_condition". May be NULL.
178 * @is_delete: True if it is a delete request.
179 *
180 * Returns 0 on sucess, negative value otherwise.
181 */
182 int ccs_write_umount_policy(char *data, struct ccs_domain_info *domain,
183 struct ccs_condition *condition,
184 const bool is_delete)
185 {
186 return ccs_update_umount_acl(data, domain, condition, is_delete);
187 }

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