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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/fs/sakura_pivot.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2828 - (show annotations) (download) (as text)
Mon Aug 3 05:36:36 2009 UTC (14 years, 10 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 7352 byte(s)


1 /*
2 * fs/sakura_pivot.c
3 *
4 * Implementation of the Domain-Free Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 1.7.0-pre 2009/07/03
9 *
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
15 #include <linux/version.h>
16 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
17 #include <linux/dcache.h>
18 #include <linux/namei.h>
19 #else
20 #include <linux/fs.h>
21 #endif
22 #include <linux/ccs_common.h>
23 #include <linux/sakura.h>
24
25 /**
26 * ccs_audit_pivot_root_log - Audit pivot_root log.
27 *
28 * @r: Pointer to "struct ccs_request_info".
29 * @new_root: New root directory.
30 * @old_root: Old root directory.
31 * @is_granted: True if this is a granted log.
32 *
33 * Returns 0 on success, negative value otherwise.
34 */
35 static int ccs_audit_pivot_root_log(struct ccs_request_info *r,
36 const char *new_root,
37 const char *old_root,
38 const bool is_granted)
39 {
40 if (!is_granted && ccs_verbose_mode(r->domain))
41 printk(KERN_WARNING "SAKURA-%s: pivot_root %s %s "
42 "denied for %s\n", ccs_get_msg(r->mode == 3), new_root,
43 old_root, ccs_get_last_name(r->domain));
44 return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_PIVOT_ROOT
45 "%s %s\n", new_root, old_root);
46 }
47
48 /**
49 * ccs_update_pivot_root_acl - Update "struct ccs_pivot_root_acl_record" list.
50 *
51 * @old_root: The name of old root directory.
52 * @new_root: The name of new root directory.
53 * @is_delete: True if it is a delete request.
54 *
55 * Returns 0 on success, negative value otherwise.
56 */
57 static int ccs_update_pivot_root_acl(const char *old_root, const char *new_root,
58 struct ccs_domain_info *domain,
59 struct ccs_condition *condition,
60 const bool is_delete)
61 {
62 struct ccs_pivot_root_acl_record *entry = NULL;
63 struct ccs_acl_info *ptr;
64 const struct ccs_path_info *saved_old_root;
65 const struct ccs_path_info *saved_new_root;
66 int error = is_delete ? -ENOENT : -ENOMEM;
67 if (!ccs_is_correct_path(old_root, 1, 0, 1) ||
68 !ccs_is_correct_path(new_root, 1, 0, 1))
69 return -EINVAL;
70 saved_old_root = ccs_get_name(old_root);
71 saved_new_root = ccs_get_name(new_root);
72 if (!saved_old_root || !saved_new_root)
73 goto out;
74 if (!is_delete)
75 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
76 mutex_lock(&ccs_policy_lock);
77 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
78 struct ccs_pivot_root_acl_record *acl;
79 if (ccs_acl_type1(ptr) != TYPE_PIVOT_ROOT_ACL)
80 continue;
81 if (ptr->cond != condition)
82 continue;
83 acl = container_of(ptr, struct ccs_pivot_root_acl_record, head);
84 if (acl->old_root != saved_old_root ||
85 acl->new_root != saved_new_root)
86 continue;
87 if (is_delete)
88 error = ccs_del_domain_acl(ptr);
89 else
90 error = ccs_add_domain_acl(NULL, ptr);
91 break;
92 }
93 if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
94 entry->head.type = TYPE_PIVOT_ROOT_ACL;
95 entry->head.cond = condition;
96 entry->old_root = saved_old_root;
97 saved_old_root = NULL;
98 entry->new_root = saved_new_root;
99 saved_new_root = NULL;
100 error = ccs_add_domain_acl(domain, &entry->head);
101 entry = NULL;
102 error = 0;
103 }
104 mutex_unlock(&ccs_policy_lock);
105 out:
106 ccs_put_name(saved_old_root);
107 ccs_put_name(saved_new_root);
108 kfree(entry);
109 return error;
110 }
111
112 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
113 #define PATH_or_NAMEIDATA path
114 #else
115 #define PATH_or_NAMEIDATA nameidata
116 #endif
117 /**
118 * ccs_check_pivot_root_permission2 - Check permission for pivot_root().
119 *
120 * @old_path: Pointer to "struct path" (for 2.6.27 and later).
121 * Pointer to "struct nameidata" (for 2.6.26 and earlier).
122 * @new_path: Pointer to "struct path" (for 2.6.27 and later).
123 * Pointer to "struct nameidata" (for 2.6.26 and earlier).
124 *
125 * Returns 0 on success, negative value otherwise.
126 *
127 * Caller holds ccs_read_lock().
128 */
129 static int ccs_check_pivot_root_permission2(struct PATH_or_NAMEIDATA *old_path,
130 struct PATH_or_NAMEIDATA *new_path)
131 {
132 struct ccs_request_info r;
133 int error;
134 char *old_root;
135 char *new_root;
136 struct ccs_path_info old_root_dir;
137 struct ccs_path_info new_root_dir;
138 bool is_enforce;
139 ccs_check_read_lock();
140 if (!ccs_can_sleep())
141 return 0;
142 ccs_init_request_info(&r, NULL, CCS_MAC_FOR_NAMESPACE);
143 is_enforce = (r.mode == 3);
144 if (!r.mode)
145 return 0;
146 retry:
147 error = -EPERM;
148 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
149 old_root = ccs_realpath_from_dentry(old_path->path.dentry,
150 old_path->path.mnt);
151 new_root = ccs_realpath_from_dentry(new_path->path.dentry,
152 new_path->path.mnt);
153 #else
154 old_root = ccs_realpath_from_dentry(old_path->dentry, old_path->mnt);
155 new_root = ccs_realpath_from_dentry(new_path->dentry, new_path->mnt);
156 #endif
157 if (!old_root || !new_root)
158 goto out;
159 old_root_dir.name = old_root;
160 ccs_fill_path_info(&old_root_dir);
161 new_root_dir.name = new_root;
162 ccs_fill_path_info(&new_root_dir);
163 if (old_root_dir.is_dir && new_root_dir.is_dir) {
164 struct ccs_acl_info *ptr;
165 list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) {
166 struct ccs_pivot_root_acl_record *acl;
167 if (ccs_acl_type2(ptr) != TYPE_PIVOT_ROOT_ACL)
168 continue;
169 acl = container_of(ptr,
170 struct ccs_pivot_root_acl_record,
171 head);
172 if (!ccs_path_matches_pattern(&old_root_dir,
173 acl->old_root) ||
174 !ccs_path_matches_pattern(&new_root_dir,
175 acl->new_root) ||
176 !ccs_check_condition(&r, ptr))
177 continue;
178 r.cond = ptr->cond;
179 error = 0;
180 break;
181 }
182 }
183 ccs_audit_pivot_root_log(&r, new_root, old_root, !error);
184 if (!error)
185 goto out;
186 if (is_enforce)
187 error = ccs_check_supervisor(&r, KEYWORD_ALLOW_PIVOT_ROOT
188 "%s %s\n", new_root, old_root);
189 else if (ccs_domain_quota_ok(&r))
190 ccs_update_pivot_root_acl(old_root, new_root, r.domain, NULL,
191 false);
192 out:
193 kfree(old_root);
194 kfree(new_root);
195 if (error == 1)
196 goto retry;
197 if (!is_enforce)
198 error = 0;
199 return error;
200 }
201
202 /**
203 * ccs_check_pivot_root_permission - Check permission for pivot_root().
204 *
205 * @old_path: Pointer to "struct path" (for 2.6.27 and later).
206 * Pointer to "struct nameidata" (for 2.6.26 and earlier).
207 * @new_path: Pointer to "struct path" (for 2.6.27 and later).
208 * Pointer to "struct nameidata" (for 2.6.26 and earlier).
209 *
210 * Returns 0 on success, negative value otherwise.
211 */
212 int ccs_check_pivot_root_permission(struct PATH_or_NAMEIDATA *old_path,
213 struct PATH_or_NAMEIDATA *new_path)
214 {
215 const int idx = ccs_read_lock();
216 const int error = ccs_check_pivot_root_permission2(old_path, new_path);
217 ccs_read_unlock(idx);
218 return error;
219 }
220
221 /**
222 * ccs_write_pivot_root_policy - Write "struct ccs_pivot_root_acl_record" list.
223 *
224 * @data: String to parse.
225 * @domain: Pointer to "struct ccs_domain_info".
226 * @condition: Pointer to "struct ccs_condition". May be NULL.
227 * @is_delete: True if it is a delete request.
228 *
229 * Returns 0 on success, negative value otherwise.
230 */
231 int ccs_write_pivot_root_policy(char *data, struct ccs_domain_info *domain,
232 struct ccs_condition *condition,
233 const bool is_delete)
234 {
235 char *w[2];
236 if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
237 return -EINVAL;
238 return ccs_update_pivot_root_acl(w[1], w[0], domain, condition,
239 is_delete);
240 }

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