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

Subversion リポジトリの参照

Annotation of /trunk/1.5.x/ccs-patch/fs/sakura_mount.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 815 - (hide annotations) (download) (as text)
Tue Dec 18 07:13:08 2007 UTC (16 years, 5 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 13682 byte(s)
Change log format.
1 kumaneko 111 /*
2     * fs/sakura_mount.c
3     *
4     * Implementation of the Domain-Free Mandatory Access Control.
5     *
6     * Copyright (C) 2005-2007 NTT DATA CORPORATION
7     *
8 kumaneko 813 * Version: 1.5.3-pre 2007/12/18
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     /***** SAKURA Linux start. *****/
15    
16     #include <linux/ccs_common.h>
17     #include <linux/sakura.h>
18     #include <linux/realpath.h>
19     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
20     #include <linux/namespace.h>
21     #endif
22    
23     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
24     #define MS_UNBINDABLE (1<<17) /* change to unbindable */
25     #define MS_PRIVATE (1<<18) /* change to private */
26     #define MS_SLAVE (1<<19) /* change to slave */
27     #define MS_SHARED (1<<20) /* change to shared */
28     #endif
29    
30     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
31     #include <linux/namei.h>
32     #else
33     static inline void module_put(struct module *module)
34     {
35     if (module) __MOD_DEC_USE_COUNT(module);
36     }
37     #endif
38    
39     extern const char *ccs_log_level;
40    
41     /***** KEYWORDS for mount restrictions. *****/
42    
43     #define MOUNT_BIND_KEYWORD "--bind" /* Allow to call 'mount --bind /source_dir /dest_dir' */
44     #define MOUNT_MOVE_KEYWORD "--move" /* Allow to call 'mount --move /old_dir /new_dir ' */
45     #define MOUNT_REMOUNT_KEYWORD "--remount" /* Allow to call 'mount -o remount /dir ' */
46     #define MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable" /* Allow to call 'mount --make-unbindable /dir' */
47     #define MOUNT_MAKE_PRIVATE_KEYWORD "--make-private" /* Allow to call 'mount --make-private /dir' */
48     #define MOUNT_MAKE_SLAVE_KEYWORD "--make-slave" /* Allow to call 'mount --make-slave /dir' */
49     #define MOUNT_MAKE_SHARED_KEYWORD "--make-shared" /* Allow to call 'mount --make-shared /dir' */
50    
51     /***** The structure for mount restrictions. *****/
52    
53 kumaneko 214 struct mount_entry {
54 kumaneko 722 struct list1_head list;
55 kumaneko 111 const struct path_info *dev_name;
56     const struct path_info *dir_name;
57     const struct path_info *fs_type;
58 kumaneko 325 unsigned long flags;
59 kumaneko 621 bool is_deleted;
60 kumaneko 214 };
61 kumaneko 111
62     /************************* MOUNT RESTRICTION HANDLER *************************/
63    
64 kumaneko 614 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
65 kumaneko 111 static void put_filesystem(struct file_system_type *fs)
66     {
67     module_put(fs->owner);
68     }
69 kumaneko 614 #endif
70 kumaneko 111
71 kumaneko 722 static LIST1_HEAD(mount_list);
72 kumaneko 111
73 kumaneko 621 static int AddMountACL(const char *dev_name, const char *dir_name, const char *fs_type, const unsigned long flags, const bool is_delete)
74 kumaneko 111 {
75 kumaneko 214 struct mount_entry *new_entry, *ptr;
76 kumaneko 111 const struct path_info *fs, *dev, *dir;
77 kumaneko 652 static DEFINE_MUTEX(lock);
78 kumaneko 111 int error = -ENOMEM;
79     if ((fs = SaveName(fs_type)) == NULL) return -EINVAL;
80     if (!dev_name) dev_name = "<NULL>"; /* Map dev_name to "<NULL>" for if no dev_name given. */
81     if (strcmp(fs->name, MOUNT_REMOUNT_KEYWORD) == 0) dev_name = "any"; /* Fix dev_name to "any" for remount permission. */
82     if (strcmp(fs->name, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
83     strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
84     strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
85     strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD) == 0) dev_name = "any";
86 kumaneko 813 if (!IsCorrectPath(dev_name, 0, 0, 0, __FUNCTION__) || !IsCorrectPath(dir_name, 0, 0, 0, __FUNCTION__)) return -EINVAL;
87 kumaneko 111 if ((dev = SaveName(dev_name)) == NULL || (dir = SaveName(dir_name)) == NULL) return -ENOMEM;
88 kumaneko 652 mutex_lock(&lock);
89 kumaneko 722 list1_for_each_entry(ptr, &mount_list, list) {
90 kumaneko 325 if (ptr->flags != flags || pathcmp(ptr->dev_name, dev) || pathcmp(ptr->dir_name, dir) || pathcmp(ptr->fs_type, fs)) continue;
91     error = 0;
92 kumaneko 111 if (is_delete) {
93     ptr->is_deleted = 1;
94     goto out;
95     } else {
96     if (ptr->is_deleted) {
97     ptr->is_deleted = 0;
98 kumaneko 325 goto update;
99 kumaneko 111 }
100 kumaneko 325 goto out; /* No changes. */
101 kumaneko 111 }
102     }
103     if (is_delete) {
104     error = -ENOENT;
105     goto out;
106     }
107 kumaneko 214 if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out;
108 kumaneko 111 new_entry->dev_name = dev;
109     new_entry->dir_name = dir;
110     new_entry->fs_type = fs;
111 kumaneko 325 new_entry->flags = flags;
112 kumaneko 722 list1_add_tail_mb(&new_entry->list, &mount_list);
113 kumaneko 111 error = 0;
114     ptr = new_entry;
115     update:
116     {
117     struct file_system_type *type = NULL;
118     if (strcmp(fs->name, MOUNT_REMOUNT_KEYWORD) == 0) {
119 kumaneko 325 printk("%sAllow remount %s with options 0x%lX.\n", ccs_log_level, dir->name, ptr->flags);
120 kumaneko 111 } else if (strcmp(fs->name, MOUNT_BIND_KEYWORD) == 0 || strcmp(fs->name, MOUNT_MOVE_KEYWORD) == 0) {
121 kumaneko 325 printk("%sAllow mount %s %s %s with options 0x%lX\n", ccs_log_level, fs->name, dev->name, dir->name, ptr->flags);
122 kumaneko 111 } else if (strcmp(fs->name, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
123     strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
124     strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
125     strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
126 kumaneko 325 printk("%sAllow mount %s %s with options 0x%lX.\n", ccs_log_level, fs->name, dir->name, ptr->flags);
127 kumaneko 111 } else if ((type = get_fs_type(fs->name)) != NULL && (type->fs_flags & FS_REQUIRES_DEV) != 0) {
128 kumaneko 325 printk("%sAllow mount -t %s %s %s with options 0x%lX.\n", ccs_log_level, fs->name, dev->name, dir->name, ptr->flags);
129 kumaneko 111 } else {
130 kumaneko 325 printk("%sAllow mount %s on %s with options 0x%lX.\n", ccs_log_level, fs->name, dir->name, ptr->flags);
131 kumaneko 111 }
132     if (type) put_filesystem(type);
133     }
134     out:
135 kumaneko 652 mutex_unlock(&lock);
136 kumaneko 111 return error;
137     }
138    
139 kumaneko 448 static int CheckMountPermission2(char *dev_name, char *dir_name, char *type, unsigned long flags)
140 kumaneko 111 {
141 kumaneko 815 const unsigned int mode = CheckCCSFlags(CCS_SAKURA_RESTRICT_MOUNT);
142     const bool is_enforce = (mode == 3);
143 kumaneko 357 int error = -EPERM;
144 kumaneko 815 if (!mode) return 0;
145 kumaneko 111 if (!type) type = "<NULL>";
146 kumaneko 325 if ((flags & MS_MGC_MSK) == MS_MGC_VAL) flags &= ~MS_MGC_MSK;
147     switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) {
148 kumaneko 111 case MS_REMOUNT:
149     case MS_MOVE:
150     case MS_BIND:
151     case 0:
152     break;
153     default:
154     printk("SAKURA-ERROR: %s%s%sare given for single mount operation.\n",
155 kumaneko 357 flags & MS_REMOUNT ? "'remount' " : "",
156     flags & MS_MOVE ? "'move' " : "",
157     flags & MS_BIND ? "'bind' " : "");
158 kumaneko 111 return -EINVAL;
159     }
160 kumaneko 325 switch (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)) {
161 kumaneko 111 case MS_UNBINDABLE:
162     case MS_PRIVATE:
163     case MS_SLAVE:
164     case MS_SHARED:
165     case 0:
166     break;
167     default:
168     printk("SAKURA-ERROR: %s%s%s%sare given for single mount operation.\n",
169 kumaneko 357 flags & MS_UNBINDABLE ? "'unbindable' " : "",
170     flags & MS_PRIVATE ? "'private' " : "",
171     flags & MS_SLAVE ? "'slave' " : "",
172     flags & MS_SHARED ? "'shared' " : "");
173 kumaneko 111 return -EINVAL;
174     }
175 kumaneko 325 if (flags & MS_REMOUNT) {
176 kumaneko 448 error = CheckMountPermission2(dev_name, dir_name, MOUNT_REMOUNT_KEYWORD, flags & ~MS_REMOUNT);
177 kumaneko 325 } else if (flags & MS_MOVE) {
178 kumaneko 448 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MOVE_KEYWORD, flags & ~MS_MOVE);
179 kumaneko 325 } else if (flags & MS_BIND) {
180 kumaneko 448 error = CheckMountPermission2(dev_name, dir_name, MOUNT_BIND_KEYWORD, flags & ~MS_BIND);
181 kumaneko 325 } else if (flags & MS_UNBINDABLE) {
182 kumaneko 448 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_UNBINDABLE_KEYWORD, flags & ~MS_UNBINDABLE);
183 kumaneko 325 } else if (flags & MS_PRIVATE) {
184 kumaneko 448 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_PRIVATE_KEYWORD, flags & ~MS_PRIVATE);
185 kumaneko 325 } else if (flags & MS_SLAVE) {
186 kumaneko 448 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_SLAVE_KEYWORD, flags & ~MS_SLAVE);
187 kumaneko 325 } else if (flags & MS_SHARED) {
188 kumaneko 448 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_SHARED_KEYWORD, flags & ~MS_SHARED);
189 kumaneko 111 } else {
190 kumaneko 214 struct mount_entry *ptr;
191 kumaneko 111 struct file_system_type *fstype = NULL;
192     const char *requested_dir_name = NULL;
193     const char *requested_dev_name = NULL;
194     struct path_info rdev, rdir;
195     int need_dev = 0;
196    
197 kumaneko 357 if ((requested_dir_name = realpath(dir_name)) == NULL) {
198     error = -ENOENT;
199     goto cleanup;
200     }
201 kumaneko 111 rdir.name = requested_dir_name;
202     fill_path_info(&rdir);
203 kumaneko 357
204 kumaneko 111 /* Compare fs name. */
205     if (strcmp(type, MOUNT_REMOUNT_KEYWORD) == 0) {
206     /* Needn't to resolve dev_name */
207     } else if (strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
208 kumaneko 357 strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
209     strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
210     strcmp(type, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
211 kumaneko 111 /* Needn't to resolve dev_name */
212     } else if (strcmp(type, MOUNT_BIND_KEYWORD) == 0 || strcmp(type, MOUNT_MOVE_KEYWORD) == 0) {
213 kumaneko 357 if ((requested_dev_name = realpath(dev_name)) == NULL) {
214     error = -ENOENT;
215     goto cleanup;
216     }
217 kumaneko 111 rdev.name = requested_dev_name;
218     fill_path_info(&rdev);
219 kumaneko 357 need_dev = -1; /* dev_name is a directory */
220 kumaneko 111 } else if ((fstype = get_fs_type(type)) != NULL) {
221     if (fstype->fs_flags & FS_REQUIRES_DEV) {
222 kumaneko 357 if ((requested_dev_name = realpath(dev_name)) == NULL) {
223     error = -ENOENT;
224     goto cleanup;
225     }
226 kumaneko 111 rdev.name = requested_dev_name;
227     fill_path_info(&rdev);
228 kumaneko 357 need_dev = 1; /* dev_name is a block device file */
229 kumaneko 111 }
230     } else {
231 kumaneko 357 error = -ENODEV;
232 kumaneko 111 goto cleanup;
233     }
234 kumaneko 722 list1_for_each_entry(ptr, &mount_list, list) {
235 kumaneko 111 if (ptr->is_deleted) continue;
236    
237 kumaneko 325 /* Compare options */
238     if (ptr->flags != flags) continue;
239 kumaneko 357
240 kumaneko 111 /* Compare fs name. */
241     if (strcmp(type, ptr->fs_type->name)) continue;
242    
243     /* Compare mount point. */
244     if (PathMatchesToPattern(&rdir, ptr->dir_name) == 0) continue;
245    
246     /* Compare device name. */
247     if (requested_dev_name && PathMatchesToPattern(&rdev, ptr->dev_name) == 0) continue;
248    
249     /* OK. */
250 kumaneko 357 error = 0;
251    
252 kumaneko 111 if (need_dev > 0) {
253 kumaneko 325 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount -t %s %s %s 0x%lX' accepted.\n", type, requested_dev_name, requested_dir_name, flags);
254 kumaneko 111 } else if (need_dev < 0) {
255 kumaneko 325 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount %s %s %s 0x%lX' accepted.\n", type, requested_dev_name, requested_dir_name, flags);
256 kumaneko 111 } else if (strcmp(type, MOUNT_REMOUNT_KEYWORD) == 0) {
257 kumaneko 325 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount -o remount %s 0x%lX' accepted.\n", requested_dir_name, flags);
258 kumaneko 111 } else if (strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
259 kumaneko 357 strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
260     strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
261     strcmp(type, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
262 kumaneko 325 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount %s %s 0x%lX' accepted.\n", type, requested_dir_name, flags);
263 kumaneko 111 } else {
264 kumaneko 325 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount %s on %s 0x%lX' accepted.\n", type, requested_dir_name, flags);
265 kumaneko 111 }
266     break;
267     }
268 kumaneko 357 if (error) {
269     const char *realname1 = realpath(dev_name), *realname2 = realpath(dir_name), *exename = GetEXE();
270     if (strcmp(type, MOUNT_REMOUNT_KEYWORD) == 0) {
271     printk("SAKURA-%s: mount -o remount %s 0x%lX (pid=%d:exe=%s): Permission denied.\n", GetMSG(is_enforce), realname2 ? realname2 : dir_name, flags, current->pid, exename);
272     if (is_enforce && CheckSupervisor("# %s is requesting\nmount -o remount %s 0x%lX\n", exename, realname2 ? realname2 : dir_name, flags) == 0) error = 0;
273     } else if (strcmp(type, MOUNT_BIND_KEYWORD) == 0 || strcmp(type, MOUNT_MOVE_KEYWORD) == 0) {
274     printk("SAKURA-%s: mount %s %s %s 0x%lX (pid=%d:exe=%s): Permission denied.\n", GetMSG(is_enforce), type, realname1 ? realname1 : dev_name, realname2 ? realname2 : dir_name, flags, current->pid, exename);
275     if (is_enforce && CheckSupervisor("# %s is requesting\nmount %s %s %s 0x%lX\n", exename, type, realname1 ? realname1 : dev_name, realname2 ? realname2 : dir_name, flags) == 0) error = 0;
276     } else if (strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
277     strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
278     strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
279     strcmp(type, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
280     printk("SAKURA-%s: mount %s %s 0x%lX (pid=%d:exe=%s): Permission denied.\n", GetMSG(is_enforce), type, realname2 ? realname2 : dir_name, flags, current->pid, exename);
281     if (is_enforce && CheckSupervisor("# %s is requesting\nmount %s %s 0x%lX", exename, type, realname2 ? realname2 : dir_name, flags) == 0) error = 0;
282     } else {
283     printk("SAKURA-%s: mount -t %s %s %s 0x%lX (pid=%d:exe=%s): Permission denied.\n", GetMSG(is_enforce), type, realname1 ? realname1 : dev_name, realname2 ? realname2 : dir_name, flags, current->pid, exename);
284     if (is_enforce && CheckSupervisor("# %s is requesting\nmount -t %s %s %s 0x%lX\n", exename, type, realname1 ? realname1 : dev_name, realname2 ? realname2 : dir_name, flags) == 0) error = 0;
285     }
286     ccs_free(exename);
287     ccs_free(realname2);
288     ccs_free(realname1);
289     }
290 kumaneko 815 if (error && mode == 1) {
291 kumaneko 325 AddMountACL(need_dev ? requested_dev_name : dev_name, requested_dir_name, type, flags, 0);
292 kumaneko 111 UpdateCounter(CCS_UPDATES_COUNTER_SYSTEM_POLICY);
293     }
294     cleanup:
295 kumaneko 357 ccs_free(requested_dev_name);
296     ccs_free(requested_dir_name);
297 kumaneko 111 if (fstype) put_filesystem(fstype);
298     }
299 kumaneko 357 if (!is_enforce) error = 0;
300     return error;
301 kumaneko 111 }
302 kumaneko 448
303     /* This is a wrapper to allow use of 1.4.x patch for 1.5.x . */
304     int CheckMountPermission(char *dev_name, char *dir_name, char *type, const unsigned long *flags)
305     {
306     return CheckMountPermission2(dev_name, dir_name, type, *flags);
307     }
308 kumaneko 111
309 kumaneko 621 int AddMountPolicy(char *data, const bool is_delete)
310 kumaneko 111 {
311     char *cp, *cp2;
312     const char *fs, *dev, *dir;
313 kumaneko 325 unsigned long flags = 0;
314 kumaneko 111 cp2 = data; if ((cp = strchr(cp2, ' ')) == NULL) return -EINVAL; *cp = '\0'; dev = cp2;
315     cp2 = cp + 1; if ((cp = strchr(cp2, ' ')) == NULL) return -EINVAL; *cp = '\0'; dir = cp2;
316 kumaneko 325 cp2 = cp + 1; if ((cp = strchr(cp2, ' ')) == NULL) return -EINVAL; *cp = '\0'; fs = cp2;
317     flags = simple_strtoul(cp + 1, NULL, 0);
318     return AddMountACL(dev, dir, fs, flags, is_delete);
319 kumaneko 111 }
320    
321 kumaneko 214 int ReadMountPolicy(struct io_buffer *head)
322 kumaneko 111 {
323 kumaneko 722 struct list1_head *pos;
324     list1_for_each_cookie(pos, head->read_var2, &mount_list) {
325 kumaneko 708 struct mount_entry *ptr;
326 kumaneko 722 ptr = list1_entry(pos, struct mount_entry, list);
327 kumaneko 708 if (ptr->is_deleted) continue;
328     if (io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", ptr->dev_name->name, ptr->dir_name->name, ptr->fs_type->name, ptr->flags)) return -ENOMEM;
329 kumaneko 111 }
330 kumaneko 708 return 0;
331 kumaneko 111 }
332    
333     /***** SAKURA Linux end. *****/

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