Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

Contents of /trunk/1.8.x/ccs-patch/security/ccsecurity/proc_if.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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