mount.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. * security/tomoyo/mount.c
  3. *
  4. * Copyright (C) 2005-2010 NTT DATA CORPORATION
  5. */
  6. #include <linux/slab.h>
  7. #include "common.h"
  8. /* Keywords for mount restrictions. */
  9. /* Allow to call 'mount --bind /source_dir /dest_dir' */
  10. #define TOMOYO_MOUNT_BIND_KEYWORD "--bind"
  11. /* Allow to call 'mount --move /old_dir /new_dir ' */
  12. #define TOMOYO_MOUNT_MOVE_KEYWORD "--move"
  13. /* Allow to call 'mount -o remount /dir ' */
  14. #define TOMOYO_MOUNT_REMOUNT_KEYWORD "--remount"
  15. /* Allow to call 'mount --make-unbindable /dir' */
  16. #define TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable"
  17. /* Allow to call 'mount --make-private /dir' */
  18. #define TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD "--make-private"
  19. /* Allow to call 'mount --make-slave /dir' */
  20. #define TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD "--make-slave"
  21. /* Allow to call 'mount --make-shared /dir' */
  22. #define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared"
  23. /**
  24. * tomoyo_encode2: Encode binary string to ascii string.
  25. *
  26. * @str: String in binary format.
  27. *
  28. * Returns pointer to @str in ascii format on success, NULL otherwise.
  29. *
  30. * This function uses kzalloc(), so caller must kfree() if this function
  31. * didn't return NULL.
  32. */
  33. static char *tomoyo_encode2(const char *str)
  34. {
  35. int len = 0;
  36. const char *p = str;
  37. char *cp;
  38. char *cp0;
  39. if (!p)
  40. return NULL;
  41. while (*p) {
  42. const unsigned char c = *p++;
  43. if (c == '\\')
  44. len += 2;
  45. else if (c > ' ' && c < 127)
  46. len++;
  47. else
  48. len += 4;
  49. }
  50. len++;
  51. /* Reserve space for appending "/". */
  52. cp = kzalloc(len + 10, GFP_NOFS);
  53. if (!cp)
  54. return NULL;
  55. cp0 = cp;
  56. p = str;
  57. while (*p) {
  58. const unsigned char c = *p++;
  59. if (c == '\\') {
  60. *cp++ = '\\';
  61. *cp++ = '\\';
  62. } else if (c > ' ' && c < 127) {
  63. *cp++ = c;
  64. } else {
  65. *cp++ = '\\';
  66. *cp++ = (c >> 6) + '0';
  67. *cp++ = ((c >> 3) & 7) + '0';
  68. *cp++ = (c & 7) + '0';
  69. }
  70. }
  71. return cp0;
  72. }
  73. /**
  74. * tomoyo_mount_acl2 - Check permission for mount() operation.
  75. *
  76. * @r: Pointer to "struct tomoyo_request_info".
  77. * @dev_name: Name of device file.
  78. * @dir: Pointer to "struct path".
  79. * @type: Name of filesystem type.
  80. * @flags: Mount options.
  81. *
  82. * Returns 0 on success, negative value otherwise.
  83. *
  84. * Caller holds tomoyo_read_lock().
  85. */
  86. static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name,
  87. struct path *dir, char *type, unsigned long flags)
  88. {
  89. struct path path;
  90. struct tomoyo_acl_info *ptr;
  91. struct file_system_type *fstype = NULL;
  92. const char *requested_type = NULL;
  93. const char *requested_dir_name = NULL;
  94. const char *requested_dev_name = NULL;
  95. struct tomoyo_path_info rtype;
  96. struct tomoyo_path_info rdev;
  97. struct tomoyo_path_info rdir;
  98. int need_dev = 0;
  99. int error = -ENOMEM;
  100. /* Get fstype. */
  101. requested_type = tomoyo_encode2(type);
  102. if (!requested_type)
  103. goto out;
  104. rtype.name = requested_type;
  105. tomoyo_fill_path_info(&rtype);
  106. /* Get mount point. */
  107. requested_dir_name = tomoyo_realpath_from_path(dir);
  108. if (!requested_dir_name) {
  109. error = -ENOMEM;
  110. goto out;
  111. }
  112. rdir.name = requested_dir_name;
  113. tomoyo_fill_path_info(&rdir);
  114. /* Compare fs name. */
  115. if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) {
  116. /* dev_name is ignored. */
  117. } else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
  118. !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) ||
  119. !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) ||
  120. !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) {
  121. /* dev_name is ignored. */
  122. } else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) ||
  123. !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) {
  124. need_dev = -1; /* dev_name is a directory */
  125. } else {
  126. fstype = get_fs_type(type);
  127. if (!fstype) {
  128. error = -ENODEV;
  129. goto out;
  130. }
  131. if (fstype->fs_flags & FS_REQUIRES_DEV)
  132. /* dev_name is a block device file. */
  133. need_dev = 1;
  134. }
  135. if (need_dev) {
  136. /* Get mount point or device file. */
  137. if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
  138. error = -ENOENT;
  139. goto out;
  140. }
  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_encode2(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. list_for_each_entry_rcu(ptr, &r->domain->acl_info_list, list) {
  159. struct tomoyo_mount_acl *acl;
  160. if (ptr->type != TOMOYO_TYPE_MOUNT_ACL)
  161. continue;
  162. acl = container_of(ptr, struct tomoyo_mount_acl, head);
  163. if (acl->is_deleted ||
  164. !tomoyo_compare_number_union(flags, &acl->flags) ||
  165. !tomoyo_compare_name_union(&rtype, &acl->fs_type) ||
  166. !tomoyo_compare_name_union(&rdir, &acl->dir_name) ||
  167. (need_dev &&
  168. !tomoyo_compare_name_union(&rdev, &acl->dev_name)))
  169. continue;
  170. error = 0;
  171. break;
  172. }
  173. if (error) {
  174. const char *dev = tomoyo_get_file_pattern(&rdev)->name;
  175. const char *dir = tomoyo_get_file_pattern(&rdir)->name;
  176. int len = strlen(dev) + strlen(dir) + strlen(requested_type)
  177. + 64;
  178. char *buf = kzalloc(len, GFP_NOFS);
  179. if (buf) {
  180. snprintf(buf, len - 1, "%s %s %s 0x%lX",
  181. dev, dir, requested_type, flags);
  182. tomoyo_write_mount_policy(buf, r->domain, false);
  183. kfree(buf);
  184. }
  185. }
  186. out:
  187. kfree(requested_dev_name);
  188. kfree(requested_dir_name);
  189. if (fstype)
  190. put_filesystem(fstype);
  191. kfree(requested_type);
  192. return error;
  193. }
  194. /**
  195. * tomoyo_mount_acl - Check permission for mount() operation.
  196. *
  197. * @r: Pointer to "struct tomoyo_request_info".
  198. * @dev_name: Name of device file.
  199. * @dir: Pointer to "struct path".
  200. * @type: Name of filesystem type.
  201. * @flags: Mount options.
  202. *
  203. * Returns 0 on success, negative value otherwise.
  204. *
  205. * Caller holds tomoyo_read_lock().
  206. */
  207. static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
  208. struct path *dir, char *type, unsigned long flags)
  209. {
  210. int error;
  211. error = -EPERM;
  212. if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
  213. flags &= ~MS_MGC_MSK;
  214. switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) {
  215. case MS_REMOUNT:
  216. case MS_MOVE:
  217. case MS_BIND:
  218. case 0:
  219. break;
  220. default:
  221. printk(KERN_WARNING "ERROR: "
  222. "%s%s%sare given for single mount operation.\n",
  223. flags & MS_REMOUNT ? "'remount' " : "",
  224. flags & MS_MOVE ? "'move' " : "",
  225. flags & MS_BIND ? "'bind' " : "");
  226. return -EINVAL;
  227. }
  228. switch (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)) {
  229. case MS_UNBINDABLE:
  230. case MS_PRIVATE:
  231. case MS_SLAVE:
  232. case MS_SHARED:
  233. case 0:
  234. break;
  235. default:
  236. printk(KERN_WARNING "ERROR: "
  237. "%s%s%s%sare given for single mount operation.\n",
  238. flags & MS_UNBINDABLE ? "'unbindable' " : "",
  239. flags & MS_PRIVATE ? "'private' " : "",
  240. flags & MS_SLAVE ? "'slave' " : "",
  241. flags & MS_SHARED ? "'shared' " : "");
  242. return -EINVAL;
  243. }
  244. if (flags & MS_REMOUNT)
  245. error = tomoyo_mount_acl(r, dev_name, dir,
  246. TOMOYO_MOUNT_REMOUNT_KEYWORD,
  247. flags & ~MS_REMOUNT);
  248. else if (flags & MS_MOVE)
  249. error = tomoyo_mount_acl(r, dev_name, dir,
  250. TOMOYO_MOUNT_MOVE_KEYWORD,
  251. flags & ~MS_MOVE);
  252. else if (flags & MS_BIND)
  253. error = tomoyo_mount_acl(r, dev_name, dir,
  254. TOMOYO_MOUNT_BIND_KEYWORD,
  255. flags & ~MS_BIND);
  256. else if (flags & MS_UNBINDABLE)
  257. error = tomoyo_mount_acl(r, dev_name, dir,
  258. TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD,
  259. flags & ~MS_UNBINDABLE);
  260. else if (flags & MS_PRIVATE)
  261. error = tomoyo_mount_acl(r, dev_name, dir,
  262. TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD,
  263. flags & ~MS_PRIVATE);
  264. else if (flags & MS_SLAVE)
  265. error = tomoyo_mount_acl(r, dev_name, dir,
  266. TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD,
  267. flags & ~MS_SLAVE);
  268. else if (flags & MS_SHARED)
  269. error = tomoyo_mount_acl(r, dev_name, dir,
  270. TOMOYO_MOUNT_MAKE_SHARED_KEYWORD,
  271. flags & ~MS_SHARED);
  272. else
  273. error = tomoyo_mount_acl2(r, dev_name, dir, type, flags);
  274. if (r->mode != TOMOYO_CONFIG_ENFORCING)
  275. error = 0;
  276. return error;
  277. }
  278. /**
  279. * tomoyo_mount_permission - Check permission for mount() operation.
  280. *
  281. * @dev_name: Name of device file.
  282. * @path: Pointer to "struct path".
  283. * @type: Name of filesystem type. May be NULL.
  284. * @flags: Mount options.
  285. * @data_page: Optional data. May be NULL.
  286. *
  287. * Returns 0 on success, negative value otherwise.
  288. */
  289. int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
  290. unsigned long flags, void *data_page)
  291. {
  292. struct tomoyo_request_info r;
  293. int error;
  294. int idx;
  295. if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED)
  296. return 0;
  297. if (!type)
  298. type = "<NULL>";
  299. idx = tomoyo_read_lock();
  300. error = tomoyo_mount_acl(&r, dev_name, path, type, flags);
  301. tomoyo_read_unlock(idx);
  302. return error;
  303. }
  304. /**
  305. * tomoyo_write_mount_policy - Write "struct tomoyo_mount_acl" list.
  306. *
  307. * @data: String to parse.
  308. * @domain: Pointer to "struct tomoyo_domain_info".
  309. * @is_delete: True if it is a delete request.
  310. *
  311. * Returns 0 on success, negative value otherwise.
  312. */
  313. int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain,
  314. const bool is_delete)
  315. {
  316. struct tomoyo_acl_info *ptr;
  317. struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
  318. int error = is_delete ? -ENOENT : -ENOMEM;
  319. char *w[4];
  320. if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0])
  321. return -EINVAL;
  322. if (!tomoyo_parse_name_union(w[0], &e.dev_name) ||
  323. !tomoyo_parse_name_union(w[1], &e.dir_name) ||
  324. !tomoyo_parse_name_union(w[2], &e.fs_type) ||
  325. !tomoyo_parse_number_union(w[3], &e.flags))
  326. goto out;
  327. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  328. goto out;
  329. list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
  330. struct tomoyo_mount_acl *acl =
  331. container_of(ptr, struct tomoyo_mount_acl, head);
  332. if (!tomoyo_is_same_mount_acl(acl, &e))
  333. continue;
  334. acl->is_deleted = is_delete;
  335. error = 0;
  336. break;
  337. }
  338. if (!is_delete && error) {
  339. struct tomoyo_mount_acl *entry =
  340. tomoyo_commit_ok(&e, sizeof(e));
  341. if (entry) {
  342. list_add_tail_rcu(&entry->head.list,
  343. &domain->acl_info_list);
  344. error = 0;
  345. }
  346. }
  347. mutex_unlock(&tomoyo_policy_lock);
  348. out:
  349. tomoyo_put_name_union(&e.dev_name);
  350. tomoyo_put_name_union(&e.dir_name);
  351. tomoyo_put_name_union(&e.fs_type);
  352. tomoyo_put_number_union(&e.flags);
  353. return error;
  354. }