Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mount.c
Go to the documentation of this file.
1 /*
2  * security/tomoyo/mount.c
3  *
4  * Copyright (C) 2005-2011 NTT DATA CORPORATION
5  */
6 
7 #include <linux/slab.h>
8 #include "common.h"
9 
10 /* String table for special mount operations. */
11 static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = {
12  [TOMOYO_MOUNT_BIND] = "--bind",
13  [TOMOYO_MOUNT_MOVE] = "--move",
14  [TOMOYO_MOUNT_REMOUNT] = "--remount",
15  [TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
16  [TOMOYO_MOUNT_MAKE_PRIVATE] = "--make-private",
17  [TOMOYO_MOUNT_MAKE_SLAVE] = "--make-slave",
18  [TOMOYO_MOUNT_MAKE_SHARED] = "--make-shared",
19 };
20 
28 static int tomoyo_audit_mount_log(struct tomoyo_request_info *r)
29 {
30  return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n",
31  r->param.mount.dev->name,
32  r->param.mount.dir->name,
33  r->param.mount.type->name,
34  r->param.mount.flags);
35 }
36 
45 static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
46  const struct tomoyo_acl_info *ptr)
47 {
48  const struct tomoyo_mount_acl *acl =
49  container_of(ptr, typeof(*acl), head);
50  return tomoyo_compare_number_union(r->param.mount.flags,
51  &acl->flags) &&
53  &acl->fs_type) &&
55  &acl->dir_name) &&
56  (!r->param.mount.need_dev ||
58  &acl->dev_name));
59 }
60 
74 static int tomoyo_mount_acl(struct tomoyo_request_info *r,
75  const char *dev_name,
76  struct path *dir, const char *type,
77  unsigned long flags)
78 {
79  struct tomoyo_obj_info obj = { };
80  struct path path;
81  struct file_system_type *fstype = NULL;
82  const char *requested_type = NULL;
83  const char *requested_dir_name = NULL;
84  const char *requested_dev_name = NULL;
85  struct tomoyo_path_info rtype;
86  struct tomoyo_path_info rdev;
87  struct tomoyo_path_info rdir;
88  int need_dev = 0;
89  int error = -ENOMEM;
90  r->obj = &obj;
91 
92  /* Get fstype. */
93  requested_type = tomoyo_encode(type);
94  if (!requested_type)
95  goto out;
96  rtype.name = requested_type;
98 
99  /* Get mount point. */
100  obj.path2 = *dir;
101  requested_dir_name = tomoyo_realpath_from_path(dir);
102  if (!requested_dir_name) {
103  error = -ENOMEM;
104  goto out;
105  }
106  rdir.name = requested_dir_name;
107  tomoyo_fill_path_info(&rdir);
108 
109  /* Compare fs name. */
110  if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) {
111  /* dev_name is ignored. */
112  } else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] ||
113  type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] ||
114  type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] ||
115  type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) {
116  /* dev_name is ignored. */
117  } else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] ||
118  type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) {
119  need_dev = -1; /* dev_name is a directory */
120  } else {
121  fstype = get_fs_type(type);
122  if (!fstype) {
123  error = -ENODEV;
124  goto out;
125  }
126  if (fstype->fs_flags & FS_REQUIRES_DEV)
127  /* dev_name is a block device file. */
128  need_dev = 1;
129  }
130  if (need_dev) {
131  /* Get mount point or device file. */
132  if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
133  error = -ENOENT;
134  goto out;
135  }
136  obj.path1 = path;
137  requested_dev_name = tomoyo_realpath_from_path(&path);
138  if (!requested_dev_name) {
139  error = -ENOENT;
140  goto out;
141  }
142  } else {
143  /* Map dev_name to "<NULL>" if no dev_name given. */
144  if (!dev_name)
145  dev_name = "<NULL>";
146  requested_dev_name = tomoyo_encode(dev_name);
147  if (!requested_dev_name) {
148  error = -ENOMEM;
149  goto out;
150  }
151  }
152  rdev.name = requested_dev_name;
155  r->param.mount.need_dev = need_dev;
156  r->param.mount.dev = &rdev;
157  r->param.mount.dir = &rdir;
158  r->param.mount.type = &rtype;
159  r->param.mount.flags = flags;
160  do {
161  tomoyo_check_acl(r, tomoyo_check_mount_acl);
162  error = tomoyo_audit_mount_log(r);
163  } while (error == TOMOYO_RETRY_REQUEST);
164  out:
165  kfree(requested_dev_name);
166  kfree(requested_dir_name);
167  if (fstype)
168  put_filesystem(fstype);
169  kfree(requested_type);
170  /* Drop refcount obtained by kern_path(). */
171  if (obj.path1.dentry)
172  path_put(&obj.path1);
173  return error;
174 }
175 
187 int tomoyo_mount_permission(const char *dev_name, struct path *path,
188  const char *type, unsigned long flags,
189  void *data_page)
190 {
191  struct tomoyo_request_info r;
192  int error;
193  int idx;
194 
197  return 0;
198  if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
199  flags &= ~MS_MGC_MSK;
200  if (flags & MS_REMOUNT) {
201  type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];
202  flags &= ~MS_REMOUNT;
203  } else if (flags & MS_BIND) {
204  type = tomoyo_mounts[TOMOYO_MOUNT_BIND];
205  flags &= ~MS_BIND;
206  } else if (flags & MS_SHARED) {
207  if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
208  return -EINVAL;
209  type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
210  flags &= ~MS_SHARED;
211  } else if (flags & MS_PRIVATE) {
212  if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
213  return -EINVAL;
214  type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];
215  flags &= ~MS_PRIVATE;
216  } else if (flags & MS_SLAVE) {
217  if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
218  return -EINVAL;
219  type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];
220  flags &= ~MS_SLAVE;
221  } else if (flags & MS_UNBINDABLE) {
222  if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
223  return -EINVAL;
224  type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
225  flags &= ~MS_UNBINDABLE;
226  } else if (flags & MS_MOVE) {
227  type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
228  flags &= ~MS_MOVE;
229  }
230  if (!type)
231  type = "<NULL>";
232  idx = tomoyo_read_lock();
233  error = tomoyo_mount_acl(&r, dev_name, path, type, flags);
234  tomoyo_read_unlock(idx);
235  return error;
236 }