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.6.6-pre 2008/12/01 |
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 |
|
15 |
#include <linux/ccs_common.h> |
16 |
#include <linux/sakura.h> |
17 |
#include <linux/realpath.h> |
18 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) |
19 |
#include <linux/namespace.h> |
20 |
#endif |
21 |
|
22 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) |
23 |
#define MS_UNBINDABLE (1<<17) /* change to unbindable */ |
24 |
#define MS_PRIVATE (1<<18) /* change to private */ |
25 |
#define MS_SLAVE (1<<19) /* change to slave */ |
26 |
#define MS_SHARED (1<<20) /* change to shared */ |
27 |
#endif |
28 |
|
29 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) |
30 |
#include <linux/namei.h> |
31 |
#else |
32 |
/* For compatibility with older kernels. */ |
33 |
static inline void module_put(struct module *module) |
34 |
{ |
35 |
if (module) |
36 |
__MOD_DEC_USE_COUNT(module); |
37 |
} |
38 |
#endif |
39 |
|
40 |
/* Keywords for mount restrictions. */ |
41 |
|
42 |
/* Allow to call 'mount --bind /source_dir /dest_dir' */ |
43 |
#define MOUNT_BIND_KEYWORD "--bind" |
44 |
/* Allow to call 'mount --move /old_dir /new_dir ' */ |
45 |
#define MOUNT_MOVE_KEYWORD "--move" |
46 |
/* Allow to call 'mount -o remount /dir ' */ |
47 |
#define MOUNT_REMOUNT_KEYWORD "--remount" |
48 |
/* Allow to call 'mount --make-unbindable /dir' */ |
49 |
#define MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable" |
50 |
/* Allow to call 'mount --make-private /dir' */ |
51 |
#define MOUNT_MAKE_PRIVATE_KEYWORD "--make-private" |
52 |
/* Allow to call 'mount --make-slave /dir' */ |
53 |
#define MOUNT_MAKE_SLAVE_KEYWORD "--make-slave" |
54 |
/* Allow to call 'mount --make-shared /dir' */ |
55 |
#define MOUNT_MAKE_SHARED_KEYWORD "--make-shared" |
56 |
|
57 |
/* Structure for "allow_mount" keyword. */ |
58 |
struct mount_entry { |
59 |
struct list1_head list; |
60 |
const struct path_info *dev_name; |
61 |
const struct path_info *dir_name; |
62 |
const struct path_info *fs_type; |
63 |
unsigned long flags; |
64 |
bool is_deleted; |
65 |
}; |
66 |
|
67 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) |
68 |
/* For compatibility with older kernels. */ |
69 |
static void put_filesystem(struct file_system_type *fs) |
70 |
{ |
71 |
module_put(fs->owner); |
72 |
} |
73 |
#endif |
74 |
|
75 |
/* The list for "struct mount_entry". */ |
76 |
static LIST1_HEAD(mount_list); |
77 |
|
78 |
/** |
79 |
* update_mount_acl - Update "struct mount_entry" list. |
80 |
* |
81 |
* @dev_name: Name of device file. |
82 |
* @dir_name: Name of mount point. |
83 |
* @fs_type: Name of filesystem. |
84 |
* @flags: Mount options. |
85 |
* @is_delete: True if it is a delete request. |
86 |
* |
87 |
* Returns 0 on success, negative value otherwise. |
88 |
*/ |
89 |
static int update_mount_acl(const char *dev_name, const char *dir_name, |
90 |
const char *fs_type, const unsigned long flags, |
91 |
const bool is_delete) |
92 |
{ |
93 |
struct file_system_type *type = NULL; |
94 |
struct mount_entry *new_entry; |
95 |
struct mount_entry *ptr; |
96 |
const struct path_info *fs; |
97 |
const struct path_info *dev; |
98 |
const struct path_info *dir; |
99 |
static DEFINE_MUTEX(lock); |
100 |
int error = -ENOMEM; |
101 |
fs = ccs_save_name(fs_type); |
102 |
if (!fs) |
103 |
return -EINVAL; |
104 |
if (!dev_name) |
105 |
/* Map dev_name to "<NULL>" for if no dev_name given. */ |
106 |
dev_name = "<NULL>"; |
107 |
if (!strcmp(fs->name, MOUNT_REMOUNT_KEYWORD)) |
108 |
/* Fix dev_name to "any" for remount permission. */ |
109 |
dev_name = "any"; |
110 |
if (!strcmp(fs->name, MOUNT_MAKE_UNBINDABLE_KEYWORD) || |
111 |
!strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) || |
112 |
!strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) || |
113 |
!strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD)) |
114 |
dev_name = "any"; |
115 |
if (!ccs_is_correct_path(dev_name, 0, 0, 0, __func__) || |
116 |
!ccs_is_correct_path(dir_name, 0, 0, 0, __func__)) |
117 |
return -EINVAL; |
118 |
dev = ccs_save_name(dev_name); |
119 |
dir = ccs_save_name(dir_name); |
120 |
if (!dev || !dir) |
121 |
return -ENOMEM; |
122 |
mutex_lock(&lock); |
123 |
list1_for_each_entry(ptr, &mount_list, list) { |
124 |
if (ptr->flags != flags || |
125 |
ccs_pathcmp(ptr->dev_name, dev) || |
126 |
ccs_pathcmp(ptr->dir_name, dir) || |
127 |
ccs_pathcmp(ptr->fs_type, fs)) |
128 |
continue; |
129 |
error = 0; |
130 |
if (is_delete) { |
131 |
ptr->is_deleted = true; |
132 |
goto out; |
133 |
} else { |
134 |
if (ptr->is_deleted) { |
135 |
ptr->is_deleted = false; |
136 |
goto update; |
137 |
} |
138 |
goto out; /* No changes. */ |
139 |
} |
140 |
} |
141 |
if (is_delete) { |
142 |
error = -ENOENT; |
143 |
goto out; |
144 |
} |
145 |
new_entry = ccs_alloc_element(sizeof(*new_entry)); |
146 |
if (!new_entry) |
147 |
goto out; |
148 |
new_entry->dev_name = dev; |
149 |
new_entry->dir_name = dir; |
150 |
new_entry->fs_type = fs; |
151 |
new_entry->flags = flags; |
152 |
list1_add_tail_mb(&new_entry->list, &mount_list); |
153 |
error = 0; |
154 |
ptr = new_entry; |
155 |
update: |
156 |
if (!strcmp(fs->name, MOUNT_REMOUNT_KEYWORD)) { |
157 |
printk(KERN_CONT "%sAllow remount %s with options 0x%lX.\n", |
158 |
ccs_log_level, dir->name, ptr->flags); |
159 |
} else if (!strcmp(fs->name, MOUNT_BIND_KEYWORD) |
160 |
|| !strcmp(fs->name, MOUNT_MOVE_KEYWORD)) { |
161 |
printk(KERN_CONT "%sAllow mount %s %s %s with options 0x%lX\n", |
162 |
ccs_log_level, fs->name, dev->name, dir->name, |
163 |
ptr->flags); |
164 |
} else if (!strcmp(fs->name, MOUNT_MAKE_UNBINDABLE_KEYWORD) || |
165 |
!strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) || |
166 |
!strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) || |
167 |
!strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD)) { |
168 |
printk(KERN_CONT "%sAllow mount %s %s with options 0x%lX.\n", |
169 |
ccs_log_level, fs->name, dir->name, ptr->flags); |
170 |
} else { |
171 |
type = get_fs_type(fs->name); |
172 |
if (type && (type->fs_flags & FS_REQUIRES_DEV) != 0) |
173 |
printk(KERN_CONT "%sAllow mount -t %s %s %s " |
174 |
"with options 0x%lX.\n", ccs_log_level, |
175 |
fs->name, dev->name, dir->name, ptr->flags); |
176 |
else |
177 |
printk(KERN_CONT "%sAllow mount %s on %s " |
178 |
"with options 0x%lX.\n", ccs_log_level, |
179 |
fs->name, dir->name, ptr->flags); |
180 |
} |
181 |
if (type) |
182 |
put_filesystem(type); |
183 |
out: |
184 |
mutex_unlock(&lock); |
185 |
ccs_update_counter(CCS_UPDATES_COUNTER_SYSTEM_POLICY); |
186 |
return error; |
187 |
} |
188 |
|
189 |
/** |
190 |
* print_success - Print success messages. |
191 |
* |
192 |
* @dev_name: Name of device file. |
193 |
* @dir_name: Name of mount point. |
194 |
* @type: Name of filesystem type. |
195 |
* @flags: Mount options. |
196 |
* @need_dev: Type of @dev_name. |
197 |
* |
198 |
* Returns nothing. |
199 |
*/ |
200 |
static void print_success(const char *dev_name, const char *dir_name, |
201 |
const char *type, const unsigned long flags, |
202 |
const int need_dev) |
203 |
{ |
204 |
if (need_dev > 0) { |
205 |
printk(KERN_DEBUG "SAKURA-NOTICE: " |
206 |
"'mount -t %s %s %s 0x%lX' accepted.\n", |
207 |
type, dev_name, dir_name, flags); |
208 |
} else if (need_dev < 0) { |
209 |
printk(KERN_DEBUG "SAKURA-NOTICE: " |
210 |
"'mount %s %s %s 0x%lX' accepted.\n", |
211 |
type, dev_name, dir_name, flags); |
212 |
} else if (!strcmp(type, MOUNT_REMOUNT_KEYWORD)) { |
213 |
printk(KERN_DEBUG "SAKURA-NOTICE: " |
214 |
"'mount -o remount %s 0x%lX' accepted.\n", |
215 |
dir_name, flags); |
216 |
} else if (!strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) || |
217 |
!strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) || |
218 |
!strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) || |
219 |
!strcmp(type, MOUNT_MAKE_SHARED_KEYWORD)) { |
220 |
printk(KERN_DEBUG "SAKURA-NOTICE: " |
221 |
"'mount %s %s 0x%lX' accepted.\n", |
222 |
type, dir_name, flags); |
223 |
} else { |
224 |
printk(KERN_DEBUG "SAKURA-NOTICE: " |
225 |
"'mount %s on %s 0x%lX' accepted.\n", |
226 |
type, dir_name, flags); |
227 |
} |
228 |
} |
229 |
|
230 |
/** |
231 |
* print_error - Print error messages. |
232 |
* |
233 |
* @r: Pointer to "struct ccs_request_info". |
234 |
* @dev_name: Name of device file. |
235 |
* @dir_name: Name of mount point. |
236 |
* @type: Name of filesystem type. |
237 |
* @flags: Mount options. |
238 |
* @error: Error value. |
239 |
* |
240 |
* Returns 0 if permitted by the administrator's decision, negative value |
241 |
* otherwise. |
242 |
*/ |
243 |
static int print_error(struct ccs_request_info *r, |
244 |
const char *dev_name, const char *dir_name, |
245 |
const char *type, const unsigned long flags, |
246 |
int error) |
247 |
{ |
248 |
const bool is_enforce = (r->mode == 3); |
249 |
const char *realname1 = ccs_realpath(dev_name); |
250 |
const char *realname2 = ccs_realpath(dir_name); |
251 |
const char *exename = ccs_get_exe(); |
252 |
const pid_t pid = (pid_t) sys_getpid(); |
253 |
if (!strcmp(type, MOUNT_REMOUNT_KEYWORD)) { |
254 |
printk(KERN_WARNING "SAKURA-%s: mount -o remount %s 0x%lX " |
255 |
"(pid=%d:exe=%s): Permission denied.\n", |
256 |
ccs_get_msg(is_enforce), |
257 |
realname2 ? realname2 : dir_name, |
258 |
flags, pid, exename); |
259 |
if (is_enforce) |
260 |
error = ccs_check_supervisor(r, "# %s is requesting\n" |
261 |
"mount -o remount %s " |
262 |
"0x%lX\n", exename, |
263 |
realname2 ? realname2 |
264 |
: dir_name, flags); |
265 |
} else if (!strcmp(type, MOUNT_BIND_KEYWORD) |
266 |
|| !strcmp(type, MOUNT_MOVE_KEYWORD)) { |
267 |
printk(KERN_WARNING "SAKURA-%s: mount %s %s %s 0x%lX " |
268 |
"(pid=%d:exe=%s): Permission denied.\n", |
269 |
ccs_get_msg(is_enforce), type, |
270 |
realname1 ? realname1 : dev_name, |
271 |
realname2 ? realname2 : dir_name, |
272 |
flags, pid, exename); |
273 |
if (is_enforce) |
274 |
error = ccs_check_supervisor(r, "# %s is requesting\n" |
275 |
"mount %s %s %s 0x%lX\n", |
276 |
exename, type, |
277 |
realname1 ? realname1 : |
278 |
dev_name, |
279 |
realname2 ? realname2 : |
280 |
dir_name, flags); |
281 |
} else if (!strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) || |
282 |
!strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) || |
283 |
!strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) || |
284 |
!strcmp(type, MOUNT_MAKE_SHARED_KEYWORD)) { |
285 |
printk(KERN_WARNING "SAKURA-%s: mount %s %s 0x%lX " |
286 |
"(pid=%d:exe=%s): Permission denied.\n", |
287 |
ccs_get_msg(is_enforce), type, |
288 |
realname2 ? realname2 : dir_name, |
289 |
flags, pid, exename); |
290 |
if (is_enforce) |
291 |
error = ccs_check_supervisor(r, "# %s is requesting\n" |
292 |
"mount %s %s 0x%lX", |
293 |
exename, type, |
294 |
realname2 ? realname2 : |
295 |
dir_name, flags); |
296 |
} else { |
297 |
printk(KERN_WARNING "SAKURA-%s: mount -t %s %s %s 0x%lX " |
298 |
"(pid=%d:exe=%s): Permission denied.\n", |
299 |
ccs_get_msg(is_enforce), type, |
300 |
realname1 ? realname1 : dev_name, |
301 |
realname2 ? realname2 : dir_name, |
302 |
flags, pid, exename); |
303 |
if (is_enforce) |
304 |
error = ccs_check_supervisor(r, "# %s is requesting\n" |
305 |
"mount -t %s %s %s " |
306 |
"0x%lX\n", exename, type, |
307 |
realname1 ? realname1 : |
308 |
dev_name, |
309 |
realname2 ? realname2 : |
310 |
dir_name, flags); |
311 |
} |
312 |
ccs_free(exename); |
313 |
ccs_free(realname2); |
314 |
ccs_free(realname1); |
315 |
return error; |
316 |
} |
317 |
|
318 |
/** |
319 |
* check_mount_permission2 - Check permission for mount() operation. |
320 |
* |
321 |
* @r: Pointer to "struct ccs_request_info". |
322 |
* @dev_name: Name of device file. |
323 |
* @dir_name: Name of mount point. |
324 |
* @type: Name of filesystem type. May be NULL. |
325 |
* @flags: Mount options. |
326 |
* |
327 |
* Returns 0 on success, negative value otherwise. |
328 |
*/ |
329 |
static int check_mount_permission2(struct ccs_request_info *r, |
330 |
char *dev_name, char *dir_name, char *type, |
331 |
unsigned long flags) |
332 |
{ |
333 |
const bool is_enforce = (r->mode == 3); |
334 |
int error; |
335 |
retry: |
336 |
error = -EPERM; |
337 |
if (!type) |
338 |
type = "<NULL>"; |
339 |
if ((flags & MS_MGC_MSK) == MS_MGC_VAL) |
340 |
flags &= ~MS_MGC_MSK; |
341 |
switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) { |
342 |
case MS_REMOUNT: |
343 |
case MS_MOVE: |
344 |
case MS_BIND: |
345 |
case 0: |
346 |
break; |
347 |
default: |
348 |
printk(KERN_WARNING "SAKURA-ERROR: " |
349 |
"%s%s%sare given for single mount operation.\n", |
350 |
flags & MS_REMOUNT ? "'remount' " : "", |
351 |
flags & MS_MOVE ? "'move' " : "", |
352 |
flags & MS_BIND ? "'bind' " : ""); |
353 |
return -EINVAL; |
354 |
} |
355 |
switch (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)) { |
356 |
case MS_UNBINDABLE: |
357 |
case MS_PRIVATE: |
358 |
case MS_SLAVE: |
359 |
case MS_SHARED: |
360 |
case 0: |
361 |
break; |
362 |
default: |
363 |
printk(KERN_WARNING "SAKURA-ERROR: " |
364 |
"%s%s%s%sare given for single mount operation.\n", |
365 |
flags & MS_UNBINDABLE ? "'unbindable' " : "", |
366 |
flags & MS_PRIVATE ? "'private' " : "", |
367 |
flags & MS_SLAVE ? "'slave' " : "", |
368 |
flags & MS_SHARED ? "'shared' " : ""); |
369 |
return -EINVAL; |
370 |
} |
371 |
if (flags & MS_REMOUNT) { |
372 |
error = check_mount_permission2(r, dev_name, dir_name, |
373 |
MOUNT_REMOUNT_KEYWORD, |
374 |
flags & ~MS_REMOUNT); |
375 |
} else if (flags & MS_MOVE) { |
376 |
error = check_mount_permission2(r, dev_name, dir_name, |
377 |
MOUNT_MOVE_KEYWORD, |
378 |
flags & ~MS_MOVE); |
379 |
} else if (flags & MS_BIND) { |
380 |
error = check_mount_permission2(r, dev_name, dir_name, |
381 |
MOUNT_BIND_KEYWORD, |
382 |
flags & ~MS_BIND); |
383 |
} else if (flags & MS_UNBINDABLE) { |
384 |
error = check_mount_permission2(r, dev_name, dir_name, |
385 |
MOUNT_MAKE_UNBINDABLE_KEYWORD, |
386 |
flags & ~MS_UNBINDABLE); |
387 |
} else if (flags & MS_PRIVATE) { |
388 |
error = check_mount_permission2(r, dev_name, dir_name, |
389 |
MOUNT_MAKE_PRIVATE_KEYWORD, |
390 |
flags & ~MS_PRIVATE); |
391 |
} else if (flags & MS_SLAVE) { |
392 |
error = check_mount_permission2(r, dev_name, dir_name, |
393 |
MOUNT_MAKE_SLAVE_KEYWORD, |
394 |
flags & ~MS_SLAVE); |
395 |
} else if (flags & MS_SHARED) { |
396 |
error = check_mount_permission2(r, dev_name, dir_name, |
397 |
MOUNT_MAKE_SHARED_KEYWORD, |
398 |
flags & ~MS_SHARED); |
399 |
} else { |
400 |
struct mount_entry *ptr; |
401 |
struct file_system_type *fstype = NULL; |
402 |
const char *requested_dir_name = NULL; |
403 |
const char *requested_dev_name = NULL; |
404 |
struct path_info rdev; |
405 |
struct path_info rdir; |
406 |
int need_dev = 0; |
407 |
|
408 |
requested_dir_name = ccs_realpath(dir_name); |
409 |
if (!requested_dir_name) { |
410 |
error = -ENOENT; |
411 |
goto cleanup; |
412 |
} |
413 |
rdir.name = requested_dir_name; |
414 |
ccs_fill_path_info(&rdir); |
415 |
|
416 |
/* Compare fs name. */ |
417 |
if (!strcmp(type, MOUNT_REMOUNT_KEYWORD)) { |
418 |
/* Needn't to resolve dev_name */ |
419 |
} else if (!strcmp(type, MOUNT_MAKE_UNBINDABLE_KEYWORD) || |
420 |
!strcmp(type, MOUNT_MAKE_PRIVATE_KEYWORD) || |
421 |
!strcmp(type, MOUNT_MAKE_SLAVE_KEYWORD) || |
422 |
!strcmp(type, MOUNT_MAKE_SHARED_KEYWORD)) { |
423 |
/* Needn't to resolve dev_name */ |
424 |
} else if (!strcmp(type, MOUNT_BIND_KEYWORD) || |
425 |
!strcmp(type, MOUNT_MOVE_KEYWORD)) { |
426 |
requested_dev_name = ccs_realpath(dev_name); |
427 |
if (!requested_dev_name) { |
428 |
error = -ENOENT; |
429 |
goto cleanup; |
430 |
} |
431 |
rdev.name = requested_dev_name; |
432 |
ccs_fill_path_info(&rdev); |
433 |
/* dev_name is a directory */ |
434 |
need_dev = -1; |
435 |
} else { |
436 |
fstype = get_fs_type(type); |
437 |
if (fstype) { |
438 |
if (fstype->fs_flags & FS_REQUIRES_DEV) { |
439 |
requested_dev_name |
440 |
= ccs_realpath(dev_name); |
441 |
if (!requested_dev_name) { |
442 |
error = -ENOENT; |
443 |
goto cleanup; |
444 |
} |
445 |
rdev.name = requested_dev_name; |
446 |
ccs_fill_path_info(&rdev); |
447 |
/* dev_name is a block device file */ |
448 |
need_dev = 1; |
449 |
} |
450 |
} else { |
451 |
error = -ENODEV; |
452 |
goto cleanup; |
453 |
} |
454 |
} |
455 |
list1_for_each_entry(ptr, &mount_list, list) { |
456 |
if (ptr->is_deleted) |
457 |
continue; |
458 |
|
459 |
/* Compare options */ |
460 |
if (ptr->flags != flags) |
461 |
continue; |
462 |
|
463 |
/* Compare fs name. */ |
464 |
if (strcmp(type, ptr->fs_type->name)) |
465 |
continue; |
466 |
|
467 |
/* Compare mount point. */ |
468 |
if (ccs_path_matches_pattern(&rdir, ptr->dir_name) == 0) |
469 |
continue; |
470 |
|
471 |
/* Compare device name. */ |
472 |
if (requested_dev_name && |
473 |
ccs_path_matches_pattern(&rdev, ptr->dev_name) == 0) |
474 |
continue; |
475 |
|
476 |
/* OK. */ |
477 |
error = 0; |
478 |
print_success(requested_dev_name, requested_dir_name, |
479 |
type, flags, need_dev); |
480 |
break; |
481 |
} |
482 |
if (error) |
483 |
error = print_error(r, dev_name, dir_name, type, flags, |
484 |
error); |
485 |
if (error && r->mode == 1) |
486 |
update_mount_acl(need_dev ? |
487 |
requested_dev_name : dev_name, |
488 |
requested_dir_name, type, flags, 0); |
489 |
cleanup: |
490 |
ccs_free(requested_dev_name); |
491 |
ccs_free(requested_dir_name); |
492 |
if (fstype) |
493 |
put_filesystem(fstype); |
494 |
} |
495 |
if (!is_enforce) |
496 |
error = 0; |
497 |
if (error == 1) |
498 |
goto retry; |
499 |
return error; |
500 |
} |
501 |
|
502 |
/** |
503 |
* ccs_check_mount_permission - Check permission for mount() operation. |
504 |
* |
505 |
* @dev_name: Name of device file. |
506 |
* @dir_name: Name of mount point. |
507 |
* @type: Name of filesystem type. May be NULL. |
508 |
* @flags: Mount options. |
509 |
* |
510 |
* Returns 0 on success, negative value otherwise. |
511 |
*/ |
512 |
int ccs_check_mount_permission(char *dev_name, char *dir_name, char *type, |
513 |
const unsigned long *flags) |
514 |
{ |
515 |
struct ccs_request_info r; |
516 |
if (!ccs_can_sleep()) |
517 |
return 0; |
518 |
ccs_init_request_info(&r, NULL, CCS_SAKURA_RESTRICT_MOUNT); |
519 |
if (!r.mode) |
520 |
return 0; |
521 |
return check_mount_permission2(&r, dev_name, dir_name, type, *flags); |
522 |
} |
523 |
|
524 |
/** |
525 |
* ccs_write_mount_policy - Write "struct mount_entry" list. |
526 |
* |
527 |
* @data: String to parse. |
528 |
* @is_delete: True if it is a delete request. |
529 |
* |
530 |
* Returns 0 on success, negative value otherwise. |
531 |
*/ |
532 |
int ccs_write_mount_policy(char *data, const bool is_delete) |
533 |
{ |
534 |
char *cp; |
535 |
char *cp2; |
536 |
const char *fs; |
537 |
const char *dev; |
538 |
const char *dir; |
539 |
unsigned long flags = 0; |
540 |
cp2 = data; |
541 |
cp = strchr(cp2, ' '); |
542 |
if (!cp) |
543 |
return -EINVAL; |
544 |
*cp = '\0'; |
545 |
dev = cp2; |
546 |
cp2 = cp + 1; |
547 |
cp = strchr(cp2, ' '); |
548 |
if (!cp) |
549 |
return -EINVAL; |
550 |
*cp = '\0'; |
551 |
dir = cp2; |
552 |
cp2 = cp + 1; |
553 |
cp = strchr(cp2, ' '); |
554 |
if (!cp) |
555 |
return -EINVAL; |
556 |
*cp = '\0'; |
557 |
fs = cp2; |
558 |
flags = simple_strtoul(cp + 1, NULL, 0); |
559 |
return update_mount_acl(dev, dir, fs, flags, is_delete); |
560 |
} |
561 |
|
562 |
/** |
563 |
* ccs_read_mount_policy - Read "struct mount_entry" list. |
564 |
* |
565 |
* @head: Pointer to "struct ccs_io_buffer". |
566 |
* |
567 |
* Returns true on success, false otherwise. |
568 |
*/ |
569 |
bool ccs_read_mount_policy(struct ccs_io_buffer *head) |
570 |
{ |
571 |
struct list1_head *pos; |
572 |
list1_for_each_cookie(pos, head->read_var2, &mount_list) { |
573 |
struct mount_entry *ptr; |
574 |
ptr = list1_entry(pos, struct mount_entry, list); |
575 |
if (ptr->is_deleted) |
576 |
continue; |
577 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", |
578 |
ptr->dev_name->name, ptr->dir_name->name, |
579 |
ptr->fs_type->name, ptr->flags)) |
580 |
goto out; |
581 |
} |
582 |
return true; |
583 |
out: |
584 |
return false; |
585 |
} |