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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/security/ccsecurity/proc_if.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4014 - (show annotations) (download) (as text)
Sat Sep 25 08:54:30 2010 UTC (13 years, 7 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 9500 byte(s)


1 /*
2 * security/ccsecurity/proc_if.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 *
6 * Version: 1.8.0-pre 2010/09/01
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/types.h>
14 #include <linux/kernel.h>
15 #include <asm/io.h>
16 #include <linux/proc_fs.h>
17 #include <linux/module.h>
18 #include <linux/version.h>
19 #include "internal.h"
20
21 static bool ccs_check_task_acl(struct ccs_request_info *r,
22 const struct ccs_acl_info *ptr)
23 {
24 const struct ccs_task_acl *acl = container_of(ptr, typeof(*acl), head);
25 return !ccs_pathcmp(r->param.task.domainname, acl->domainname);
26 }
27
28 /**
29 * ccs_write_self - write() for /proc/ccs/self_domain interface.
30 *
31 * @file: Pointer to "struct file".
32 * @buf: Domainname to transit to.
33 * @count: Size of @buf.
34 * @ppos: Unused.
35 *
36 * Returns @count on success, negative value otherwise.
37 */
38 static ssize_t ccs_write_self(struct file *file, const char __user *buf,
39 size_t count, loff_t *ppos)
40 {
41 char *data;
42 int error;
43 if (!count || count >= CCS_EXEC_TMPSIZE - 10)
44 return -ENOMEM;
45 data = kzalloc(count + 1, CCS_GFP_FLAGS);
46 if (!data)
47 return -ENOMEM;
48 if (copy_from_user(data, buf, count)) {
49 error = -EFAULT;
50 goto out;
51 }
52 ccs_normalize_line(data);
53 if (ccs_correct_domain(data)) {
54 const int idx = ccs_read_lock();
55 struct ccs_path_info name;
56 struct ccs_request_info r;
57 name.name = data;
58 ccs_fill_path_info(&name);
59 /* Check "task manual_transit" permission. */
60 ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
61 r.param_type = CCS_TYPE_MANUAL_TASK_ACL;
62 r.param.task.domainname = &name;
63 ccs_check_acl(&r, ccs_check_task_acl);
64 if (!r.granted)
65 error = -EPERM;
66 else
67 error = ccs_assign_domain(data, r.profile,
68 ccs_current_domain()->group,
69 true) ? 0 : -ENOENT;
70 ccs_read_unlock(idx);
71 } else
72 error = -EINVAL;
73 out:
74 kfree(data);
75 return error ? error : count;
76 }
77
78 /**
79 * ccs_read_self - read() for /proc/ccs/self_domain interface.
80 *
81 * @file: Pointer to "struct file".
82 * @buf: Domainname which current thread belongs to.
83 * @count: Size of @buf.
84 * @ppos: Bytes read by now.
85 *
86 * Returns read size on success, negative value otherwise.
87 */
88 static int ccs_read_self(struct file *file, char __user *buf, size_t count,
89 loff_t *ppos)
90 {
91 const char *domain = ccs_current_domain()->domainname->name;
92 const int len = strlen(domain) - *ppos;
93 const int pos = *ppos;
94 if (pos >= len)
95 return 0;
96 if (copy_to_user(buf, domain + pos, len - pos))
97 return -EFAULT;
98 return len - pos;
99 }
100
101 /* Operations for /proc/ccs/self_domain interface. */
102 static
103 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
104 const
105 #endif
106 struct file_operations ccs_self_operations = {
107 .write = ccs_write_self,
108 .read = ccs_read_self,
109 };
110
111 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)
112 #if !defined(RHEL_VERSION) || RHEL_VERSION != 3 || !defined(RHEL_UPDATE) || RHEL_UPDATE != 9
113 /**
114 * PDE - Get "struct proc_dir_entry".
115 *
116 * @inode: Pointer to "struct inode".
117 *
118 * Returns pointer to "struct proc_dir_entry"
119 *
120 * This is for compatibility with older kernels.
121 */
122 static inline struct proc_dir_entry *PDE(const struct inode *inode)
123 {
124 return (struct proc_dir_entry *) inode->u.generic_ip;
125 }
126 #endif
127 #endif
128
129 /**
130 * ccs_open - open() for /proc/ccs/ interface.
131 *
132 * @inode: Pointer to "struct inode".
133 * @file: Pointer to "struct file".
134 *
135 * Returns 0 on success, negative value otherwise.
136 */
137 static int ccs_open(struct inode *inode, struct file *file)
138 {
139 return ccs_open_control(((u8 *) PDE(inode)->data) - ((u8 *) NULL),
140 file);
141 }
142
143 /**
144 * ccs_release - close() for /proc/ccs/ interface.
145 *
146 * @inode: Pointer to "struct inode".
147 * @file: Pointer to "struct file".
148 *
149 * Returns 0 on success, negative value otherwise.
150 */
151 static int ccs_release(struct inode *inode, struct file *file)
152 {
153 return ccs_close_control(file);
154 }
155
156 /**
157 * ccs_poll - poll() for /proc/ccs/ interface.
158 *
159 * @file: Pointer to "struct file".
160 * @wait: Pointer to "poll_table".
161 *
162 * Returns 0 on success, negative value otherwise.
163 */
164 static unsigned int ccs_poll(struct file *file, poll_table *wait)
165 {
166 return ccs_poll_control(file, wait);
167 }
168
169 /**
170 * ccs_read - read() for /proc/ccs/ interface.
171 *
172 * @file: Pointer to "struct file".
173 * @buf: Pointer to buffer.
174 * @count: Size of @buf.
175 * @ppos: Unused.
176 *
177 * Returns bytes read on success, negative value otherwise.
178 */
179 static ssize_t ccs_read(struct file *file, char __user *buf, size_t count,
180 loff_t *ppos)
181 {
182 return ccs_read_control(file, buf, count);
183 }
184
185 /**
186 * ccs_write - write() for /proc/ccs/ interface.
187 *
188 * @file: Pointer to "struct file".
189 * @buf: Pointer to buffer.
190 * @count: Size of @buf.
191 * @ppos: Unused.
192 *
193 * Returns @count on success, negative value otherwise.
194 */
195 static ssize_t ccs_write(struct file *file, const char __user *buf,
196 size_t count, loff_t *ppos)
197 {
198 return ccs_write_control(file, buf, count);
199 }
200
201 /* Operations for /proc/ccs/ interface. */
202 static
203 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
204 const
205 #endif
206 struct file_operations ccs_operations = {
207 .open = ccs_open,
208 .release = ccs_release,
209 .poll = ccs_poll,
210 .read = ccs_read,
211 .write = ccs_write,
212 };
213
214 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
215
216 struct iattr;
217
218 /**
219 * proc_notify_change - Update inode's attributes and reflect to the dentry.
220 *
221 * @dentry: Pointer to "struct dentry".
222 * @iattr: Pointer to "struct iattr".
223 *
224 * Returns 0 on success, negative value otherwise.
225 *
226 * The 2.4 kernels don't allow chmod()/chown() for files in /proc ,
227 * while the 2.6 kernels allow.
228 * To permit management of /proc/ccs/ interface by non-root user,
229 * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels
230 * by adding "struct inode_operations"->setattr hook.
231 */
232 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
233 {
234 struct inode *inode = dentry->d_inode;
235 struct proc_dir_entry *de = PDE(inode);
236 int error;
237
238 error = inode_change_ok(inode, iattr);
239 if (error)
240 goto out;
241
242 error = inode_setattr(inode, iattr);
243 if (error)
244 goto out;
245
246 de->uid = inode->i_uid;
247 de->gid = inode->i_gid;
248 de->mode = inode->i_mode;
249 out:
250 return error;
251 }
252
253 /* The inode operations for /proc/ccs/ directory. */
254 static struct inode_operations ccs_dir_inode_operations;
255
256 /* The inode operations for files under /proc/ccs/ directory. */
257 static struct inode_operations ccs_file_inode_operations;
258 #endif
259
260 /**
261 * ccs_create_entry - Create interface files under /proc/ccs/ directory.
262 *
263 * @name: The name of the interface file.
264 * @mode: The permission of the interface file.
265 * @parent: The parent directory.
266 * @key: Type of interface.
267 *
268 * Returns nothing.
269 */
270 static void __init ccs_create_entry(const char *name, const mode_t mode,
271 struct proc_dir_entry *parent,
272 const u8 key)
273 {
274 struct proc_dir_entry *entry = create_proc_entry(name, mode, parent);
275 if (entry) {
276 entry->proc_fops = &ccs_operations;
277 entry->data = ((u8 *) NULL) + key;
278 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
279 if (entry->proc_iops)
280 ccs_file_inode_operations = *entry->proc_iops;
281 if (!ccs_file_inode_operations.setattr)
282 ccs_file_inode_operations.setattr = proc_notify_change;
283 entry->proc_iops = &ccs_file_inode_operations;
284 #endif
285 }
286 }
287
288 /**
289 * ccs_proc_init - Initialize /proc/ccs/ interface.
290 *
291 * Returns 0.
292 */
293 static void __init ccs_proc_init(void)
294 {
295 struct proc_dir_entry *ccs_dir = proc_mkdir("ccs", NULL);
296 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
297 if (ccs_dir->proc_iops)
298 ccs_dir_inode_operations = *ccs_dir->proc_iops;
299 if (!ccs_dir_inode_operations.setattr)
300 ccs_dir_inode_operations.setattr = proc_notify_change;
301 ccs_dir->proc_iops = &ccs_dir_inode_operations;
302 #endif
303 ccs_create_entry("query", 0600, ccs_dir, CCS_QUERY);
304 ccs_create_entry("domain_policy", 0600, ccs_dir, CCS_DOMAINPOLICY);
305 ccs_create_entry("exception_policy", 0600, ccs_dir,
306 CCS_EXCEPTIONPOLICY);
307 ccs_create_entry("grant_log", 0400, ccs_dir, CCS_GRANTLOG);
308 ccs_create_entry("reject_log", 0400, ccs_dir, CCS_REJECTLOG);
309 ccs_create_entry(".domain_status", 0600, ccs_dir, CCS_DOMAIN_STATUS);
310 ccs_create_entry(".process_status", 0600, ccs_dir,
311 CCS_PROCESS_STATUS);
312 ccs_create_entry("meminfo", 0600, ccs_dir, CCS_MEMINFO);
313 ccs_create_entry("profile", 0600, ccs_dir, CCS_PROFILE);
314 ccs_create_entry("manager", 0600, ccs_dir, CCS_MANAGER);
315 ccs_create_entry("version", 0400, ccs_dir, CCS_VERSION);
316 ccs_create_entry(".execute_handler", 0666, ccs_dir,
317 CCS_EXECUTE_HANDLER);
318 {
319 struct proc_dir_entry *e = create_proc_entry("self_domain",
320 0666, ccs_dir);
321 if (e)
322 e->proc_fops = &ccs_self_operations;
323 }
324 }
325
326 static int __init ccs_init_module(void)
327 {
328 int i;
329 for (i = 0; i < CCS_MAX_POLICY; i++)
330 INIT_LIST_HEAD(&ccs_policy_list[i]);
331 for (i = 0; i < CCS_MAX_GROUP; i++)
332 INIT_LIST_HEAD(&ccs_group_list[i]);
333 for (i = 0; i < CCS_MAX_LIST; i++)
334 INIT_LIST_HEAD(&ccs_shared_list[i]);
335 if (ccsecurity_ops.disabled)
336 return -EINVAL;
337 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 0)
338 MOD_INC_USE_COUNT;
339 #endif
340 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
341 if (init_srcu_struct(&ccs_ss))
342 panic("Out of memory.");
343 #endif
344 ccs_proc_init();
345 ccs_mm_init();
346 ccs_capability_init();
347 ccs_file_init();
348 ccs_network_init();
349 ccs_signal_init();
350 ccs_mount_init();
351 ccs_policy_io_init();
352 ccs_domain_init();
353 return 0;
354 }
355
356 MODULE_LICENSE("GPL");
357 module_init(ccs_init_module);

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