5 |
* |
* |
6 |
* Copyright (C) 2005-2007 NTT DATA CORPORATION |
* Copyright (C) 2005-2007 NTT DATA CORPORATION |
7 |
* |
* |
8 |
* Version: 1.5.2-pre 2007/10/19 |
* Version: 1.5.3-pre 2007/12/18 |
9 |
* |
* |
10 |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
11 |
* See README.ccs for ChangeLog. |
* See README.ccs for ChangeLog. |
51 |
/***** The structure for mount restrictions. *****/ |
/***** The structure for mount restrictions. *****/ |
52 |
|
|
53 |
struct mount_entry { |
struct mount_entry { |
54 |
struct mount_entry *next; |
struct list1_head list; |
55 |
const struct path_info *dev_name; |
const struct path_info *dev_name; |
56 |
const struct path_info *dir_name; |
const struct path_info *dir_name; |
57 |
const struct path_info *fs_type; |
const struct path_info *fs_type; |
68 |
} |
} |
69 |
#endif |
#endif |
70 |
|
|
71 |
static struct mount_entry *mount_list = NULL; |
static LIST1_HEAD(mount_list); |
72 |
|
|
73 |
static int AddMountACL(const char *dev_name, const char *dir_name, const char *fs_type, const unsigned long flags, const bool is_delete) |
static int AddMountACL(const char *dev_name, const char *dir_name, const char *fs_type, const unsigned long flags, const bool is_delete) |
74 |
{ |
{ |
75 |
struct mount_entry *new_entry, *ptr; |
struct mount_entry *new_entry, *ptr; |
76 |
const struct path_info *fs, *dev, *dir; |
const struct path_info *fs, *dev, *dir; |
77 |
static DECLARE_MUTEX(lock); |
static DEFINE_MUTEX(lock); |
78 |
int error = -ENOMEM; |
int error = -ENOMEM; |
79 |
if ((fs = SaveName(fs_type)) == NULL) return -EINVAL; |
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. */ |
if (!dev_name) dev_name = "<NULL>"; /* Map dev_name to "<NULL>" for if no dev_name given. */ |
83 |
strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 || |
strcmp(fs->name, MOUNT_MAKE_PRIVATE_KEYWORD) == 0 || |
84 |
strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) == 0 || |
strcmp(fs->name, MOUNT_MAKE_SLAVE_KEYWORD) == 0 || |
85 |
strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD) == 0) dev_name = "any"; |
strcmp(fs->name, MOUNT_MAKE_SHARED_KEYWORD) == 0) dev_name = "any"; |
86 |
if (!IsCorrectPath(dev_name, 0, 0, 0, __FUNCTION__) || !IsCorrectPath(dir_name, 1, 0, 1, __FUNCTION__)) return -EINVAL; |
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; |
if ((dev = SaveName(dev_name)) == NULL || (dir = SaveName(dir_name)) == NULL) return -ENOMEM; |
88 |
down(&lock); |
mutex_lock(&lock); |
89 |
for (ptr = mount_list; ptr; ptr = ptr->next) { |
list1_for_each_entry(ptr, &mount_list, list) { |
90 |
if (ptr->flags != flags || pathcmp(ptr->dev_name, dev) || pathcmp(ptr->dir_name, dir) || pathcmp(ptr->fs_type, fs)) continue; |
if (ptr->flags != flags || pathcmp(ptr->dev_name, dev) || pathcmp(ptr->dir_name, dir) || pathcmp(ptr->fs_type, fs)) continue; |
91 |
error = 0; |
error = 0; |
92 |
if (is_delete) { |
if (is_delete) { |
109 |
new_entry->dir_name = dir; |
new_entry->dir_name = dir; |
110 |
new_entry->fs_type = fs; |
new_entry->fs_type = fs; |
111 |
new_entry->flags = flags; |
new_entry->flags = flags; |
112 |
mb(); /* Instead of using spinlock. */ |
list1_add_tail_mb(&new_entry->list, &mount_list); |
|
if ((ptr = mount_list) != NULL) { |
|
|
while (ptr->next) ptr = ptr->next; ptr->next = new_entry; |
|
|
} else { |
|
|
mount_list = new_entry; |
|
|
} |
|
113 |
error = 0; |
error = 0; |
114 |
ptr = new_entry; |
ptr = new_entry; |
115 |
update: |
update: |
132 |
if (type) put_filesystem(type); |
if (type) put_filesystem(type); |
133 |
} |
} |
134 |
out: |
out: |
135 |
up(&lock); |
mutex_unlock(&lock); |
136 |
return error; |
return error; |
137 |
} |
} |
138 |
|
|
139 |
static int CheckMountPermission2(char *dev_name, char *dir_name, char *type, unsigned long flags) |
static int CheckMountPermission2(char *dev_name, char *dir_name, char *type, unsigned long flags) |
140 |
{ |
{ |
141 |
const bool is_enforce = CheckCCSEnforce(CCS_SAKURA_RESTRICT_MOUNT); |
const unsigned int mode = CheckCCSFlags(CCS_SAKURA_RESTRICT_MOUNT); |
142 |
|
const bool is_enforce = (mode == 3); |
143 |
int error = -EPERM; |
int error = -EPERM; |
144 |
if (!CheckCCSFlags(CCS_SAKURA_RESTRICT_MOUNT)) return 0; |
if (!mode) return 0; |
145 |
if (!type) type = "<NULL>"; |
if (!type) type = "<NULL>"; |
146 |
if ((flags & MS_MGC_MSK) == MS_MGC_VAL) flags &= ~MS_MGC_MSK; |
if ((flags & MS_MGC_MSK) == MS_MGC_VAL) flags &= ~MS_MGC_MSK; |
147 |
switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) { |
switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) { |
231 |
error = -ENODEV; |
error = -ENODEV; |
232 |
goto cleanup; |
goto cleanup; |
233 |
} |
} |
234 |
for (ptr = mount_list; ptr; ptr = ptr->next) { |
list1_for_each_entry(ptr, &mount_list, list) { |
235 |
if (ptr->is_deleted) continue; |
if (ptr->is_deleted) continue; |
236 |
|
|
237 |
/* Compare options */ |
/* Compare options */ |
287 |
ccs_free(realname2); |
ccs_free(realname2); |
288 |
ccs_free(realname1); |
ccs_free(realname1); |
289 |
} |
} |
290 |
if (error && !is_enforce && CheckCCSAccept(CCS_SAKURA_RESTRICT_MOUNT, NULL)) { |
if (error && mode == 1) { |
291 |
AddMountACL(need_dev ? requested_dev_name : dev_name, requested_dir_name, type, flags, 0); |
AddMountACL(need_dev ? requested_dev_name : dev_name, requested_dir_name, type, flags, 0); |
292 |
UpdateCounter(CCS_UPDATES_COUNTER_SYSTEM_POLICY); |
UpdateCounter(CCS_UPDATES_COUNTER_SYSTEM_POLICY); |
293 |
} |
} |
305 |
{ |
{ |
306 |
return CheckMountPermission2(dev_name, dir_name, type, *flags); |
return CheckMountPermission2(dev_name, dir_name, type, *flags); |
307 |
} |
} |
|
EXPORT_SYMBOL(CheckMountPermission); |
|
308 |
|
|
309 |
int AddMountPolicy(char *data, const bool is_delete) |
int AddMountPolicy(char *data, const bool is_delete) |
310 |
{ |
{ |
320 |
|
|
321 |
int ReadMountPolicy(struct io_buffer *head) |
int ReadMountPolicy(struct io_buffer *head) |
322 |
{ |
{ |
323 |
struct mount_entry *ptr = head->read_var2; |
struct list1_head *pos; |
324 |
if (!ptr) ptr = mount_list; |
list1_for_each_cookie(pos, head->read_var2, &mount_list) { |
325 |
while (ptr) { |
struct mount_entry *ptr; |
326 |
head->read_var2 = ptr; |
ptr = list1_entry(pos, struct mount_entry, list); |
327 |
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; |
if (ptr->is_deleted) continue; |
328 |
ptr = ptr->next; |
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 |
} |
} |
330 |
return ptr ? -ENOMEM : 0; |
return 0; |
331 |
} |
} |
332 |
|
|
333 |
/***** SAKURA Linux end. *****/ |
/***** SAKURA Linux end. *****/ |