Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/tomoyo/mount.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* security/tomoyo/mount.c
4
*
5
* Copyright (C) 2005-2011 NTT DATA CORPORATION
6
*/
7
8
#include <linux/slab.h>
9
#include <uapi/linux/mount.h>
10
#include "common.h"
11
12
/* String table for special mount operations. */
13
static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = {
14
[TOMOYO_MOUNT_BIND] = "--bind",
15
[TOMOYO_MOUNT_MOVE] = "--move",
16
[TOMOYO_MOUNT_REMOUNT] = "--remount",
17
[TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
18
[TOMOYO_MOUNT_MAKE_PRIVATE] = "--make-private",
19
[TOMOYO_MOUNT_MAKE_SLAVE] = "--make-slave",
20
[TOMOYO_MOUNT_MAKE_SHARED] = "--make-shared",
21
};
22
23
/**
24
* tomoyo_audit_mount_log - Audit mount log.
25
*
26
* @r: Pointer to "struct tomoyo_request_info".
27
*
28
* Returns 0 on success, negative value otherwise.
29
*/
30
static int tomoyo_audit_mount_log(struct tomoyo_request_info *r)
31
{
32
return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n",
33
r->param.mount.dev->name,
34
r->param.mount.dir->name,
35
r->param.mount.type->name,
36
r->param.mount.flags);
37
}
38
39
/**
40
* tomoyo_check_mount_acl - Check permission for path path path number operation.
41
*
42
* @r: Pointer to "struct tomoyo_request_info".
43
* @ptr: Pointer to "struct tomoyo_acl_info".
44
*
45
* Returns true if granted, false otherwise.
46
*/
47
static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
48
const struct tomoyo_acl_info *ptr)
49
{
50
const struct tomoyo_mount_acl *acl =
51
container_of(ptr, typeof(*acl), head);
52
53
return tomoyo_compare_number_union(r->param.mount.flags,
54
&acl->flags) &&
55
tomoyo_compare_name_union(r->param.mount.type,
56
&acl->fs_type) &&
57
tomoyo_compare_name_union(r->param.mount.dir,
58
&acl->dir_name) &&
59
(!r->param.mount.need_dev ||
60
tomoyo_compare_name_union(r->param.mount.dev,
61
&acl->dev_name));
62
}
63
64
/**
65
* tomoyo_mount_acl - Check permission for mount() operation.
66
*
67
* @r: Pointer to "struct tomoyo_request_info".
68
* @dev_name: Name of device file. Maybe NULL.
69
* @dir: Pointer to "struct path".
70
* @type: Name of filesystem type.
71
* @flags: Mount options.
72
*
73
* Returns 0 on success, negative value otherwise.
74
*
75
* Caller holds tomoyo_read_lock().
76
*/
77
static int tomoyo_mount_acl(struct tomoyo_request_info *r,
78
const char *dev_name,
79
const struct path *dir, const char *type,
80
unsigned long flags)
81
{
82
struct tomoyo_obj_info obj = { };
83
struct path path;
84
struct file_system_type *fstype = NULL;
85
const char *requested_type = NULL;
86
const char *requested_dir_name = NULL;
87
const char *requested_dev_name = NULL;
88
struct tomoyo_path_info rtype;
89
struct tomoyo_path_info rdev;
90
struct tomoyo_path_info rdir;
91
int need_dev = 0;
92
int error = -ENOMEM;
93
94
r->obj = &obj;
95
96
/* Get fstype. */
97
requested_type = tomoyo_encode(type);
98
if (!requested_type)
99
goto out;
100
rtype.name = requested_type;
101
tomoyo_fill_path_info(&rtype);
102
103
/* Get mount point. */
104
obj.path2 = *dir;
105
requested_dir_name = tomoyo_realpath_from_path(dir);
106
if (!requested_dir_name) {
107
error = -ENOMEM;
108
goto out;
109
}
110
rdir.name = requested_dir_name;
111
tomoyo_fill_path_info(&rdir);
112
113
/* Compare fs name. */
114
if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) {
115
/* dev_name is ignored. */
116
} else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] ||
117
type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] ||
118
type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] ||
119
type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) {
120
/* dev_name is ignored. */
121
} else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] ||
122
type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) {
123
need_dev = -1; /* dev_name is a directory */
124
} else {
125
fstype = get_fs_type(type);
126
if (!fstype) {
127
error = -ENODEV;
128
goto out;
129
}
130
if (fstype->fs_flags & FS_REQUIRES_DEV)
131
/* dev_name is a block device file. */
132
need_dev = 1;
133
}
134
if (need_dev) {
135
/* Get mount point or device file. */
136
if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
137
error = -ENOENT;
138
goto out;
139
}
140
obj.path1 = path;
141
requested_dev_name = tomoyo_realpath_from_path(&path);
142
if (!requested_dev_name) {
143
error = -ENOENT;
144
goto out;
145
}
146
} else {
147
/* Map dev_name to "<NULL>" if no dev_name given. */
148
if (!dev_name)
149
dev_name = "<NULL>";
150
requested_dev_name = tomoyo_encode(dev_name);
151
if (!requested_dev_name) {
152
error = -ENOMEM;
153
goto out;
154
}
155
}
156
rdev.name = requested_dev_name;
157
tomoyo_fill_path_info(&rdev);
158
r->param_type = TOMOYO_TYPE_MOUNT_ACL;
159
r->param.mount.need_dev = need_dev;
160
r->param.mount.dev = &rdev;
161
r->param.mount.dir = &rdir;
162
r->param.mount.type = &rtype;
163
r->param.mount.flags = flags;
164
do {
165
tomoyo_check_acl(r, tomoyo_check_mount_acl);
166
error = tomoyo_audit_mount_log(r);
167
} while (error == TOMOYO_RETRY_REQUEST);
168
out:
169
kfree(requested_dev_name);
170
kfree(requested_dir_name);
171
if (fstype)
172
put_filesystem(fstype);
173
kfree(requested_type);
174
/* Drop refcount obtained by kern_path(). */
175
if (obj.path1.dentry)
176
path_put(&obj.path1);
177
return error;
178
}
179
180
/**
181
* tomoyo_mount_permission - Check permission for mount() operation.
182
*
183
* @dev_name: Name of device file. Maybe NULL.
184
* @path: Pointer to "struct path".
185
* @type: Name of filesystem type. Maybe NULL.
186
* @flags: Mount options.
187
* @data_page: Optional data. Maybe NULL.
188
*
189
* Returns 0 on success, negative value otherwise.
190
*/
191
int tomoyo_mount_permission(const char *dev_name, const struct path *path,
192
const char *type, unsigned long flags,
193
void *data_page)
194
{
195
struct tomoyo_request_info r;
196
int error;
197
int idx;
198
199
if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT)
200
== TOMOYO_CONFIG_DISABLED)
201
return 0;
202
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
203
flags &= ~MS_MGC_MSK;
204
if (flags & MS_REMOUNT) {
205
type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];
206
flags &= ~MS_REMOUNT;
207
} else if (flags & MS_BIND) {
208
type = tomoyo_mounts[TOMOYO_MOUNT_BIND];
209
flags &= ~MS_BIND;
210
} else if (flags & MS_SHARED) {
211
if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
212
return -EINVAL;
213
type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
214
flags &= ~MS_SHARED;
215
} else if (flags & MS_PRIVATE) {
216
if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
217
return -EINVAL;
218
type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];
219
flags &= ~MS_PRIVATE;
220
} else if (flags & MS_SLAVE) {
221
if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
222
return -EINVAL;
223
type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];
224
flags &= ~MS_SLAVE;
225
} else if (flags & MS_UNBINDABLE) {
226
if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
227
return -EINVAL;
228
type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
229
flags &= ~MS_UNBINDABLE;
230
} else if (flags & MS_MOVE) {
231
type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
232
flags &= ~MS_MOVE;
233
}
234
if (!type)
235
type = "<NULL>";
236
idx = tomoyo_read_lock();
237
error = tomoyo_mount_acl(&r, dev_name, path, type, flags);
238
tomoyo_read_unlock(idx);
239
return error;
240
}
241
242