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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1507 - (show annotations) (download) (as text)
Tue Sep 2 06:45:13 2008 UTC (15 years, 9 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 13805 byte(s)


1 /*
2 * fs/sakura_mount.c
3 *
4 * Implementation of the Domain-Free Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2008 NTT DATA CORPORATION
7 *
8 * Version: 1.5.5 2008/09/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 /***** 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 struct mount_entry {
54 struct mount_entry *next;
55 const struct path_info *dev_name;
56 const struct path_info *dir_name;
57 const struct path_info *fs_type;
58 unsigned long flags;
59 int is_deleted;
60 };
61
62 /************************* MOUNT RESTRICTION HANDLER *************************/
63
64 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
65 static void put_filesystem(struct file_system_type *fs)
66 {
67 module_put(fs->owner);
68 }
69 #endif
70
71 static struct mount_entry *mount_list = NULL;
72
73 static int AddMountACL(const char *dev_name, const char *dir_name, const char *fs_type, const unsigned long flags, const int is_delete)
74 {
75 struct mount_entry *new_entry, *ptr;
76 const struct path_info *fs, *dev, *dir;
77 static DECLARE_MUTEX(lock);
78 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 if (!IsCorrectPath(dev_name, 0, 0, 0, __FUNCTION__) || !IsCorrectPath(dir_name, 0, 0, 0, __FUNCTION__)) return -EINVAL;
87 if ((dev = SaveName(dev_name)) == NULL || (dir = SaveName(dir_name)) == NULL) return -ENOMEM;
88 down(&lock);
89 for (ptr = mount_list; ptr; ptr = ptr->next) {
90 if (ptr->flags != flags || pathcmp(ptr->dev_name, dev) || pathcmp(ptr->dir_name, dir) || pathcmp(ptr->fs_type, fs)) continue;
91 error = 0;
92 if (is_delete) {
93 ptr->is_deleted = 1;
94 goto out;
95 } else {
96 if (ptr->is_deleted) {
97 ptr->is_deleted = 0;
98 goto update;
99 }
100 goto out; /* No changes. */
101 }
102 }
103 if (is_delete) {
104 error = -ENOENT;
105 goto out;
106 }
107 if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out;
108 new_entry->dev_name = dev;
109 new_entry->dir_name = dir;
110 new_entry->fs_type = fs;
111 new_entry->flags = flags;
112 mb(); /* Avoid out-of-order execution. */
113 if ((ptr = mount_list) != NULL) {
114 while (ptr->next) ptr = ptr->next; ptr->next = new_entry;
115 } else {
116 mount_list = new_entry;
117 }
118 error = 0;
119 ptr = new_entry;
120 update:
121 {
122 struct file_system_type *type = NULL;
123 if (strcmp(fs->name, MOUNT_REMOUNT_KEYWORD) == 0) {
124 printk("%sAllow remount %s with options 0x%lX.\n", ccs_log_level, dir->name, ptr->flags);
125 } else if (strcmp(fs->name, MOUNT_BIND_KEYWORD) == 0 || strcmp(fs->name, MOUNT_MOVE_KEYWORD) == 0) {
126 printk("%sAllow mount %s %s %s with options 0x%lX\n", ccs_log_level, fs->name, dev->name, dir->name, ptr->flags);
127 } else if (strcmp(fs->name, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
128 strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
129 strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
130 strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
131 printk("%sAllow mount %s %s with options 0x%lX.\n", ccs_log_level, fs->name, dir->name, ptr->flags);
132 } else if ((type = get_fs_type(fs->name)) != NULL && (type->fs_flags & FS_REQUIRES_DEV) != 0) {
133 printk("%sAllow mount -t %s %s %s with options 0x%lX.\n", ccs_log_level, fs->name, dev->name, dir->name, ptr->flags);
134 } else {
135 printk("%sAllow mount %s on %s with options 0x%lX.\n", ccs_log_level, fs->name, dir->name, ptr->flags);
136 }
137 if (type) put_filesystem(type);
138 }
139 out:
140 up(&lock);
141 return error;
142 }
143
144 static int CheckMountPermission2(char *dev_name, char *dir_name, char *type, unsigned long flags)
145 {
146 const int is_enforce = CheckCCSEnforce(CCS_SAKURA_RESTRICT_MOUNT);
147 int error = -EPERM;
148 if (!CheckCCSFlags(CCS_SAKURA_RESTRICT_MOUNT)) return 0;
149 if (!type) type = "<NULL>";
150 if ((flags & MS_MGC_MSK) == MS_MGC_VAL) flags &= ~MS_MGC_MSK;
151 switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) {
152 case MS_REMOUNT:
153 case MS_MOVE:
154 case MS_BIND:
155 case 0:
156 break;
157 default:
158 printk("SAKURA-ERROR: %s%s%sare given for single mount operation.\n",
159 flags & MS_REMOUNT ? "'remount' " : "",
160 flags & MS_MOVE ? "'move' " : "",
161 flags & MS_BIND ? "'bind' " : "");
162 return -EINVAL;
163 }
164 switch (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)) {
165 case MS_UNBINDABLE:
166 case MS_PRIVATE:
167 case MS_SLAVE:
168 case MS_SHARED:
169 case 0:
170 break;
171 default:
172 printk("SAKURA-ERROR: %s%s%s%sare given for single mount operation.\n",
173 flags & MS_UNBINDABLE ? "'unbindable' " : "",
174 flags & MS_PRIVATE ? "'private' " : "",
175 flags & MS_SLAVE ? "'slave' " : "",
176 flags & MS_SHARED ? "'shared' " : "");
177 return -EINVAL;
178 }
179 if (flags & MS_REMOUNT) {
180 error = CheckMountPermission2(dev_name, dir_name, MOUNT_REMOUNT_KEYWORD, flags & ~MS_REMOUNT);
181 } else if (flags & MS_MOVE) {
182 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MOVE_KEYWORD, flags & ~MS_MOVE);
183 } else if (flags & MS_BIND) {
184 error = CheckMountPermission2(dev_name, dir_name, MOUNT_BIND_KEYWORD, flags & ~MS_BIND);
185 } else if (flags & MS_UNBINDABLE) {
186 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_UNBINDABLE_KEYWORD, flags & ~MS_UNBINDABLE);
187 } else if (flags & MS_PRIVATE) {
188 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_PRIVATE_KEYWORD, flags & ~MS_PRIVATE);
189 } else if (flags & MS_SLAVE) {
190 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_SLAVE_KEYWORD, flags & ~MS_SLAVE);
191 } else if (flags & MS_SHARED) {
192 error = CheckMountPermission2(dev_name, dir_name, MOUNT_MAKE_SHARED_KEYWORD, flags & ~MS_SHARED);
193 } else {
194 struct mount_entry *ptr;
195 struct file_system_type *fstype = NULL;
196 const char *requested_dir_name = NULL;
197 const char *requested_dev_name = NULL;
198 struct path_info rdev, rdir;
199 int need_dev = 0;
200
201 if ((requested_dir_name = realpath(dir_name)) == NULL) {
202 error = -ENOENT;
203 goto cleanup;
204 }
205 rdir.name = requested_dir_name;
206 fill_path_info(&rdir);
207
208 /* Compare fs name. */
209 if (strcmp(type, MOUNT_REMOUNT_KEYWORD) == 0) {
210 /* Needn't to resolve dev_name */
211 } else if (strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
212 strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
213 strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
214 strcmp(type, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
215 /* Needn't to resolve dev_name */
216 } else if (strcmp(type, MOUNT_BIND_KEYWORD) == 0 || strcmp(type, MOUNT_MOVE_KEYWORD) == 0) {
217 if ((requested_dev_name = realpath(dev_name)) == NULL) {
218 error = -ENOENT;
219 goto cleanup;
220 }
221 rdev.name = requested_dev_name;
222 fill_path_info(&rdev);
223 need_dev = -1; /* dev_name is a directory */
224 } else if ((fstype = get_fs_type(type)) != NULL) {
225 if (fstype->fs_flags & FS_REQUIRES_DEV) {
226 if ((requested_dev_name = realpath(dev_name)) == NULL) {
227 error = -ENOENT;
228 goto cleanup;
229 }
230 rdev.name = requested_dev_name;
231 fill_path_info(&rdev);
232 need_dev = 1; /* dev_name is a block device file */
233 }
234 } else {
235 error = -ENODEV;
236 goto cleanup;
237 }
238 for (ptr = mount_list; ptr; ptr = ptr->next) {
239 if (ptr->is_deleted) continue;
240
241 /* Compare options */
242 if (ptr->flags != flags) continue;
243
244 /* Compare fs name. */
245 if (strcmp(type, ptr->fs_type->name)) continue;
246
247 /* Compare mount point. */
248 if (PathMatchesToPattern(&rdir, ptr->dir_name) == 0) continue;
249
250 /* Compare device name. */
251 if (requested_dev_name && PathMatchesToPattern(&rdev, ptr->dev_name) == 0) continue;
252
253 /* OK. */
254 error = 0;
255
256 if (need_dev > 0) {
257 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount -t %s %s %s 0x%lX' accepted.\n", type, requested_dev_name, requested_dir_name, flags);
258 } else if (need_dev < 0) {
259 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount %s %s %s 0x%lX' accepted.\n", type, requested_dev_name, requested_dir_name, flags);
260 } else if (strcmp(type, MOUNT_REMOUNT_KEYWORD) == 0) {
261 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount -o remount %s 0x%lX' accepted.\n", requested_dir_name, flags);
262 } else if (strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
263 strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
264 strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
265 strcmp(type, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
266 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount %s %s 0x%lX' accepted.\n", type, requested_dir_name, flags);
267 } else {
268 printk(KERN_DEBUG "SAKURA-NOTICE: 'mount %s on %s 0x%lX' accepted.\n", type, requested_dir_name, flags);
269 }
270 break;
271 }
272 if (error) {
273 const char *realname1 = realpath(dev_name), *realname2 = realpath(dir_name), *exename = GetEXE();
274 if (strcmp(type, MOUNT_REMOUNT_KEYWORD) == 0) {
275 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);
276 if (is_enforce && CheckSupervisor("# %s is requesting\nmount -o remount %s 0x%lX\n", exename, realname2 ? realname2 : dir_name, flags) == 0) error = 0;
277 } else if (strcmp(type, MOUNT_BIND_KEYWORD) == 0 || strcmp(type, MOUNT_MOVE_KEYWORD) == 0) {
278 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);
279 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;
280 } else if (strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) == 0 ||
281 strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 ||
282 strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) == 0 ||
283 strcmp(type, MOUNT_MAKE_SHARED_KEYWORD) == 0) {
284 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);
285 if (is_enforce && CheckSupervisor("# %s is requesting\nmount %s %s 0x%lX", exename, type, realname2 ? realname2 : dir_name, flags) == 0) error = 0;
286 } else {
287 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);
288 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;
289 }
290 ccs_free(exename);
291 ccs_free(realname2);
292 ccs_free(realname1);
293 }
294 if (error && !is_enforce && CheckCCSAccept(CCS_SAKURA_RESTRICT_MOUNT, NULL)) {
295 AddMountACL(need_dev ? requested_dev_name : dev_name, requested_dir_name, type, flags, 0);
296 UpdateCounter(CCS_UPDATES_COUNTER_SYSTEM_POLICY);
297 }
298 cleanup:
299 ccs_free(requested_dev_name);
300 ccs_free(requested_dir_name);
301 if (fstype) put_filesystem(fstype);
302 }
303 if (!is_enforce) error = 0;
304 return error;
305 }
306
307 /* This is a wrapper to allow use of 1.4.x patch for 1.5.x . */
308 int CheckMountPermission(char *dev_name, char *dir_name, char *type, const unsigned long *flags)
309 {
310 return CheckMountPermission2(dev_name, dir_name, type, *flags);
311 }
312
313 int AddMountPolicy(char *data, const int is_delete)
314 {
315 char *cp, *cp2;
316 const char *fs, *dev, *dir;
317 unsigned long flags = 0;
318 cp2 = data; if ((cp = strchr(cp2, ' ')) == NULL) return -EINVAL; *cp = '\0'; dev = cp2;
319 cp2 = cp + 1; if ((cp = strchr(cp2, ' ')) == NULL) return -EINVAL; *cp = '\0'; dir = cp2;
320 cp2 = cp + 1; if ((cp = strchr(cp2, ' ')) == NULL) return -EINVAL; *cp = '\0'; fs = cp2;
321 flags = simple_strtoul(cp + 1, NULL, 0);
322 return AddMountACL(dev, dir, fs, flags, is_delete);
323 }
324
325 int ReadMountPolicy(struct io_buffer *head)
326 {
327 struct mount_entry *ptr = head->read_var2;
328 if (!ptr) ptr = mount_list;
329 while (ptr) {
330 head->read_var2 = ptr;
331 if (ptr->is_deleted == 0 && 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)) break;
332 ptr = ptr->next;
333 }
334 return ptr ? -ENOMEM : 0;
335 }
336
337 /***** SAKURA Linux end. *****/

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