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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3871 - (show annotations) (download) (as text)
Sun Aug 1 01:42:05 2010 UTC (13 years, 10 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 8512 byte(s)


1 /*
2 * security/ccsecurity/mount.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 *
6 * Version: 1.8.0-pre 2010/08/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/slab.h>
14 #include <linux/version.h>
15 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
16 #include <linux/dcache.h>
17 #include <linux/namei.h>
18 #endif
19 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
20 #include <linux/namespace.h>
21 #endif
22 #include "internal.h"
23
24 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
25 #define MS_UNBINDABLE (1<<17) /* change to unbindable */
26 #define MS_PRIVATE (1<<18) /* change to private */
27 #define MS_SLAVE (1<<19) /* change to slave */
28 #define MS_SHARED (1<<20) /* change to shared */
29 #endif
30
31 /* Keywords for mount restrictions. */
32
33 /* Allow to call 'mount --bind /source_dir /dest_dir' */
34 #define CCS_MOUNT_BIND_KEYWORD "--bind"
35 /* Allow to call 'mount --move /old_dir /new_dir ' */
36 #define CCS_MOUNT_MOVE_KEYWORD "--move"
37 /* Allow to call 'mount -o remount /dir ' */
38 #define CCS_MOUNT_REMOUNT_KEYWORD "--remount"
39 /* Allow to call 'mount --make-unbindable /dir' */
40 #define CCS_MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable"
41 /* Allow to call 'mount --make-private /dir' */
42 #define CCS_MOUNT_MAKE_PRIVATE_KEYWORD "--make-private"
43 /* Allow to call 'mount --make-slave /dir' */
44 #define CCS_MOUNT_MAKE_SLAVE_KEYWORD "--make-slave"
45 /* Allow to call 'mount --make-shared /dir' */
46 #define CCS_MOUNT_MAKE_SHARED_KEYWORD "--make-shared"
47
48 /**
49 * ccs_audit_mount_log - Audit mount log.
50 *
51 * @r: Pointer to "struct ccs_request_info".
52 *
53 * Returns 0 on success, negative value otherwise.
54 */
55 static int ccs_audit_mount_log(struct ccs_request_info *r)
56 {
57 const char *dev = r->param.mount.dev->name;
58 const char *dir = r->param.mount.dir->name;
59 const char *type = r->param.mount.type->name;
60 const unsigned long flags = r->param.mount.flags;
61 ccs_write_log(r, "file mount %s %s %s 0x%lX\n", dev, dir, type, flags);
62 if (r->granted)
63 return 0;
64 if (!strcmp(type, CCS_MOUNT_REMOUNT_KEYWORD))
65 ccs_warn_log(r, "file mount -o remount %s 0x%lX", dir, flags);
66 else if (!strcmp(type, CCS_MOUNT_BIND_KEYWORD)
67 || !strcmp(type, CCS_MOUNT_MOVE_KEYWORD))
68 ccs_warn_log(r, "file mount %s %s %s 0x%lX", type, dev, dir, flags);
69 else if (!strcmp(type, CCS_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
70 !strcmp(type, CCS_MOUNT_MAKE_PRIVATE_KEYWORD) ||
71 !strcmp(type, CCS_MOUNT_MAKE_SLAVE_KEYWORD) ||
72 !strcmp(type, CCS_MOUNT_MAKE_SHARED_KEYWORD))
73 ccs_warn_log(r, "file mount %s %s 0x%lX", type, dir, flags);
74 else
75 ccs_warn_log(r, "file mount -t %s %s %s 0x%lX", type, dev, dir,
76 flags);
77 return ccs_supervisor(r, "file mount %s %s %s 0x%lX\n",
78 ccs_file_pattern(r->param.mount.dev),
79 ccs_file_pattern(r->param.mount.dir), type,
80 flags);
81 }
82
83 static bool ccs_check_mount_acl(struct ccs_request_info *r,
84 const struct ccs_acl_info *ptr)
85 {
86 const struct ccs_mount_acl *acl =
87 container_of(ptr, typeof(*acl), head);
88 return ccs_compare_number_union(r->param.mount.flags, &acl->flags) &&
89 ccs_compare_name_union(r->param.mount.type, &acl->fs_type) &&
90 ccs_compare_name_union(r->param.mount.dir, &acl->dir_name) &&
91 (!r->param.mount.need_dev ||
92 ccs_compare_name_union(r->param.mount.dev, &acl->dev_name));
93 }
94
95 /**
96 * ccs_mount_acl - Check permission for mount() operation.
97 *
98 * @r: Pointer to "struct ccs_request_info".
99 * @dev_name: Name of device file.
100 * @dir: Pointer to "struct path".
101 * @type: Name of filesystem type.
102 * @flags: Mount options.
103 *
104 * Returns 0 on success, negative value otherwise.
105 *
106 * Caller holds ccs_read_lock().
107 */
108 static int ccs_mount_acl(struct ccs_request_info *r, char *dev_name,
109 struct path *dir, char *type, unsigned long flags)
110 {
111 struct ccs_obj_info obj = { };
112 struct path path;
113 struct file_system_type *fstype = NULL;
114 const char *requested_type = NULL;
115 const char *requested_dir_name = NULL;
116 const char *requested_dev_name = NULL;
117 struct ccs_path_info rtype;
118 struct ccs_path_info rdev;
119 struct ccs_path_info rdir;
120 int need_dev = 0;
121 int error = -ENOMEM;
122 r->obj = &obj;
123
124 /* Get fstype. */
125 requested_type = ccs_encode(type);
126 if (!requested_type)
127 goto out;
128 rtype.name = requested_type;
129 ccs_fill_path_info(&rtype);
130
131 /* Get mount point. */
132 obj.path2 = *dir;
133 requested_dir_name = ccs_realpath_from_path(dir);
134 if (!requested_dir_name) {
135 error = -ENOMEM;
136 goto out;
137 }
138 rdir.name = requested_dir_name;
139 ccs_fill_path_info(&rdir);
140
141 /* Compare fs name. */
142 if (!strcmp(type, CCS_MOUNT_REMOUNT_KEYWORD)) {
143 /* dev_name is ignored. */
144 } else if (!strcmp(type, CCS_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
145 !strcmp(type, CCS_MOUNT_MAKE_PRIVATE_KEYWORD) ||
146 !strcmp(type, CCS_MOUNT_MAKE_SLAVE_KEYWORD) ||
147 !strcmp(type, CCS_MOUNT_MAKE_SHARED_KEYWORD)) {
148 /* dev_name is ignored. */
149 } else if (!strcmp(type, CCS_MOUNT_BIND_KEYWORD) ||
150 !strcmp(type, CCS_MOUNT_MOVE_KEYWORD)) {
151 need_dev = -1; /* dev_name is a directory */
152 } else {
153 fstype = get_fs_type(type);
154 if (!fstype) {
155 error = -ENODEV;
156 goto out;
157 }
158 if (fstype->fs_flags & FS_REQUIRES_DEV)
159 /* dev_name is a block device file. */
160 need_dev = 1;
161 }
162 if (need_dev) {
163 /* Get mount point or device file. */
164 if (ccs_get_path(dev_name, &path)) {
165 error = -ENOENT;
166 goto out;
167 }
168 obj.path1 = path;
169 requested_dev_name = ccs_realpath_from_path(&path);
170 if (!requested_dev_name) {
171 error = -ENOENT;
172 goto out;
173 }
174 } else {
175 /* Map dev_name to "<NULL>" if no dev_name given. */
176 if (!dev_name)
177 dev_name = "<NULL>";
178 requested_dev_name = ccs_encode(dev_name);
179 if (!requested_dev_name) {
180 error = -ENOMEM;
181 goto out;
182 }
183 }
184 rdev.name = requested_dev_name;
185 ccs_fill_path_info(&rdev);
186 r->param_type = CCS_TYPE_MOUNT_ACL;
187 r->param.mount.need_dev = need_dev;
188 r->param.mount.dev = &rdev;
189 r->param.mount.dir = &rdir;
190 r->param.mount.type = &rtype;
191 r->param.mount.flags = flags;
192 do {
193 ccs_check_acl(r, ccs_check_mount_acl);
194 error = ccs_audit_mount_log(r);
195 } while (error == CCS_RETRY_REQUEST);
196 out:
197 kfree(requested_dev_name);
198 kfree(requested_dir_name);
199 if (fstype)
200 ccsecurity_exports.put_filesystem(fstype);
201 kfree(requested_type);
202 /* Drop refcount obtained by ccs_get_path(). */
203 if (obj.path1.dentry)
204 path_put(&obj.path1);
205 return error;
206 }
207
208 /**
209 * ccs_mount_permission - Check permission for mount() operation.
210 *
211 * @dev_name: Name of device file.
212 * @path: Pointer to "struct path".
213 * @type: Name of filesystem type. Maybe NULL.
214 * @flags: Mount options.
215 * @data_page: Optional data. Maybe NULL.
216 *
217 * Returns 0 on success, negative value otherwise.
218 */
219 static int __ccs_mount_permission(char *dev_name, struct path *path,
220 char *type, unsigned long flags,
221 void *data_page)
222 {
223 struct ccs_request_info r;
224 int error;
225 int idx;
226 if (ccs_init_request_info(&r, CCS_MAC_FILE_MOUNT)
227 == CCS_CONFIG_DISABLED)
228 return 0;
229 if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
230 flags &= ~MS_MGC_MSK;
231 if (flags & MS_REMOUNT) {
232 type = CCS_MOUNT_REMOUNT_KEYWORD;
233 flags &= ~MS_REMOUNT;
234 }
235 if (flags & MS_MOVE) {
236 type = CCS_MOUNT_MOVE_KEYWORD;
237 flags &= ~MS_MOVE;
238 }
239 if (flags & MS_BIND) {
240 type = CCS_MOUNT_BIND_KEYWORD;
241 flags &= ~MS_BIND;
242 }
243 if (flags & MS_UNBINDABLE) {
244 type = CCS_MOUNT_MAKE_UNBINDABLE_KEYWORD;
245 flags &= ~MS_UNBINDABLE;
246 }
247 if (flags & MS_PRIVATE) {
248 type = CCS_MOUNT_MAKE_PRIVATE_KEYWORD;
249 flags &= ~MS_PRIVATE;
250 }
251 if (flags & MS_SLAVE) {
252 type = CCS_MOUNT_MAKE_SLAVE_KEYWORD;
253 flags &= ~MS_SLAVE;
254 }
255 if (flags & MS_SHARED) {
256 type = CCS_MOUNT_MAKE_SHARED_KEYWORD;
257 flags &= ~MS_SHARED;
258 }
259 if (!type)
260 type = "<NULL>";
261 idx = ccs_read_lock();
262 error = ccs_mount_acl(&r, dev_name, path, type, flags);
263 ccs_read_unlock(idx);
264 return error;
265 }
266
267 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
268 static int ccs_old_mount_permission(char *dev_name, struct nameidata *nd,
269 char *type, unsigned long flags,
270 void *data_page)
271 {
272 struct path path = { nd->mnt, nd->dentry };
273 return __ccs_mount_permission(dev_name, &path, type, flags, data_page);
274 }
275 #endif
276
277 void __init ccs_mount_init(void)
278 {
279 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
280 ccsecurity_ops.mount_permission = __ccs_mount_permission;
281 #else
282 ccsecurity_ops.mount_permission = ccs_old_mount_permission;
283 #endif
284 }

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