realpath.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * security/tomoyo/realpath.c
  3. *
  4. * Pathname calculation functions for TOMOYO.
  5. *
  6. * Copyright (C) 2005-2010 NTT DATA CORPORATION
  7. */
  8. #include <linux/types.h>
  9. #include <linux/mount.h>
  10. #include <linux/mnt_namespace.h>
  11. #include <linux/fs_struct.h>
  12. #include <linux/magic.h>
  13. #include <linux/slab.h>
  14. #include <net/sock.h>
  15. #include "common.h"
  16. #include "../../fs/internal.h"
  17. /**
  18. * tomoyo_encode: Convert binary string to ascii string.
  19. *
  20. * @str: String in binary format.
  21. *
  22. * Returns pointer to @str in ascii format on success, NULL otherwise.
  23. *
  24. * This function uses kzalloc(), so caller must kfree() if this function
  25. * didn't return NULL.
  26. */
  27. char *tomoyo_encode(const char *str)
  28. {
  29. int len = 0;
  30. const char *p = str;
  31. char *cp;
  32. char *cp0;
  33. if (!p)
  34. return NULL;
  35. while (*p) {
  36. const unsigned char c = *p++;
  37. if (c == '\\')
  38. len += 2;
  39. else if (c > ' ' && c < 127)
  40. len++;
  41. else
  42. len += 4;
  43. }
  44. len++;
  45. /* Reserve space for appending "/". */
  46. cp = kzalloc(len + 10, GFP_NOFS);
  47. if (!cp)
  48. return NULL;
  49. cp0 = cp;
  50. p = str;
  51. while (*p) {
  52. const unsigned char c = *p++;
  53. if (c == '\\') {
  54. *cp++ = '\\';
  55. *cp++ = '\\';
  56. } else if (c > ' ' && c < 127) {
  57. *cp++ = c;
  58. } else {
  59. *cp++ = '\\';
  60. *cp++ = (c >> 6) + '0';
  61. *cp++ = ((c >> 3) & 7) + '0';
  62. *cp++ = (c & 7) + '0';
  63. }
  64. }
  65. return cp0;
  66. }
  67. /**
  68. * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
  69. *
  70. * @path: Pointer to "struct path".
  71. * @buffer: Pointer to buffer to return value in.
  72. * @buflen: Sizeof @buffer.
  73. *
  74. * Returns the buffer on success, an error code otherwise.
  75. *
  76. * If dentry is a directory, trailing '/' is appended.
  77. */
  78. static char *tomoyo_get_absolute_path(struct path *path, char * const buffer,
  79. const int buflen)
  80. {
  81. char *pos = ERR_PTR(-ENOMEM);
  82. if (buflen >= 256) {
  83. struct path ns_root = { };
  84. /* go to whatever namespace root we are under */
  85. pos = __d_path(path, &ns_root, buffer, buflen - 1);
  86. if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
  87. struct inode *inode = path->dentry->d_inode;
  88. if (inode && S_ISDIR(inode->i_mode)) {
  89. buffer[buflen - 2] = '/';
  90. buffer[buflen - 1] = '\0';
  91. }
  92. }
  93. }
  94. return pos;
  95. }
  96. /**
  97. * tomoyo_get_dentry_path - Get the path of a dentry.
  98. *
  99. * @dentry: Pointer to "struct dentry".
  100. * @buffer: Pointer to buffer to return value in.
  101. * @buflen: Sizeof @buffer.
  102. *
  103. * Returns the buffer on success, an error code otherwise.
  104. *
  105. * If dentry is a directory, trailing '/' is appended.
  106. */
  107. static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer,
  108. const int buflen)
  109. {
  110. char *pos = ERR_PTR(-ENOMEM);
  111. if (buflen >= 256) {
  112. pos = dentry_path_raw(dentry, buffer, buflen - 1);
  113. if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
  114. struct inode *inode = dentry->d_inode;
  115. if (inode && S_ISDIR(inode->i_mode)) {
  116. buffer[buflen - 2] = '/';
  117. buffer[buflen - 1] = '\0';
  118. }
  119. }
  120. }
  121. return pos;
  122. }
  123. /**
  124. * tomoyo_get_local_path - Get the path of a dentry.
  125. *
  126. * @dentry: Pointer to "struct dentry".
  127. * @buffer: Pointer to buffer to return value in.
  128. * @buflen: Sizeof @buffer.
  129. *
  130. * Returns the buffer on success, an error code otherwise.
  131. */
  132. static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
  133. const int buflen)
  134. {
  135. struct super_block *sb = dentry->d_sb;
  136. char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen);
  137. if (IS_ERR(pos))
  138. return pos;
  139. /* Convert from $PID to self if $PID is current thread. */
  140. if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
  141. char *ep;
  142. const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
  143. if (*ep == '/' && pid && pid ==
  144. task_tgid_nr_ns(current, sb->s_fs_info)) {
  145. pos = ep - 5;
  146. if (pos < buffer)
  147. goto out;
  148. memmove(pos, "/self", 5);
  149. }
  150. goto prepend_filesystem_name;
  151. }
  152. /* Use filesystem name for unnamed devices. */
  153. if (!MAJOR(sb->s_dev))
  154. goto prepend_filesystem_name;
  155. {
  156. struct inode *inode = sb->s_root->d_inode;
  157. /*
  158. * Use filesystem name if filesystem does not support rename()
  159. * operation.
  160. */
  161. if (inode->i_op && !inode->i_op->rename)
  162. goto prepend_filesystem_name;
  163. }
  164. /* Prepend device name. */
  165. {
  166. char name[64];
  167. int name_len;
  168. const dev_t dev = sb->s_dev;
  169. name[sizeof(name) - 1] = '\0';
  170. snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
  171. MINOR(dev));
  172. name_len = strlen(name);
  173. pos -= name_len;
  174. if (pos < buffer)
  175. goto out;
  176. memmove(pos, name, name_len);
  177. return pos;
  178. }
  179. /* Prepend filesystem name. */
  180. prepend_filesystem_name:
  181. {
  182. const char *name = sb->s_type->name;
  183. const int name_len = strlen(name);
  184. pos -= name_len + 1;
  185. if (pos < buffer)
  186. goto out;
  187. memmove(pos, name, name_len);
  188. pos[name_len] = ':';
  189. }
  190. return pos;
  191. out:
  192. return ERR_PTR(-ENOMEM);
  193. }
  194. /**
  195. * tomoyo_get_socket_name - Get the name of a socket.
  196. *
  197. * @path: Pointer to "struct path".
  198. * @buffer: Pointer to buffer to return value in.
  199. * @buflen: Sizeof @buffer.
  200. *
  201. * Returns the buffer.
  202. */
  203. static char *tomoyo_get_socket_name(struct path *path, char * const buffer,
  204. const int buflen)
  205. {
  206. struct inode *inode = path->dentry->d_inode;
  207. struct socket *sock = inode ? SOCKET_I(inode) : NULL;
  208. struct sock *sk = sock ? sock->sk : NULL;
  209. if (sk) {
  210. snprintf(buffer, buflen, "socket:[family=%u:type=%u:"
  211. "protocol=%u]", sk->sk_family, sk->sk_type,
  212. sk->sk_protocol);
  213. } else {
  214. snprintf(buffer, buflen, "socket:[unknown]");
  215. }
  216. return buffer;
  217. }
  218. /**
  219. * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
  220. *
  221. * @path: Pointer to "struct path".
  222. *
  223. * Returns the realpath of the given @path on success, NULL otherwise.
  224. *
  225. * If dentry is a directory, trailing '/' is appended.
  226. * Characters out of 0x20 < c < 0x7F range are converted to
  227. * \ooo style octal string.
  228. * Character \ is converted to \\ string.
  229. *
  230. * These functions use kzalloc(), so the caller must call kfree()
  231. * if these functions didn't return NULL.
  232. */
  233. char *tomoyo_realpath_from_path(struct path *path)
  234. {
  235. char *buf = NULL;
  236. char *name = NULL;
  237. unsigned int buf_len = PAGE_SIZE / 2;
  238. struct dentry *dentry = path->dentry;
  239. struct super_block *sb;
  240. if (!dentry)
  241. return NULL;
  242. sb = dentry->d_sb;
  243. while (1) {
  244. char *pos;
  245. struct inode *inode;
  246. buf_len <<= 1;
  247. kfree(buf);
  248. buf = kmalloc(buf_len, GFP_NOFS);
  249. if (!buf)
  250. break;
  251. /* To make sure that pos is '\0' terminated. */
  252. buf[buf_len - 1] = '\0';
  253. /* Get better name for socket. */
  254. if (sb->s_magic == SOCKFS_MAGIC) {
  255. pos = tomoyo_get_socket_name(path, buf, buf_len - 1);
  256. goto encode;
  257. }
  258. /* For "pipe:[\$]". */
  259. if (dentry->d_op && dentry->d_op->d_dname) {
  260. pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
  261. goto encode;
  262. }
  263. inode = sb->s_root->d_inode;
  264. /*
  265. * Get local name for filesystems without rename() operation
  266. * or dentry without vfsmount.
  267. */
  268. if (!path->mnt || (inode->i_op && !inode->i_op->rename))
  269. pos = tomoyo_get_local_path(path->dentry, buf,
  270. buf_len - 1);
  271. /* Get absolute name for the rest. */
  272. else
  273. pos = tomoyo_get_absolute_path(path, buf, buf_len - 1);
  274. encode:
  275. if (IS_ERR(pos))
  276. continue;
  277. name = tomoyo_encode(pos);
  278. break;
  279. }
  280. kfree(buf);
  281. if (!name)
  282. tomoyo_warn_oom(__func__);
  283. return name;
  284. }
  285. /**
  286. * tomoyo_realpath_nofollow - Get realpath of a pathname.
  287. *
  288. * @pathname: The pathname to solve.
  289. *
  290. * Returns the realpath of @pathname on success, NULL otherwise.
  291. */
  292. char *tomoyo_realpath_nofollow(const char *pathname)
  293. {
  294. struct path path;
  295. if (pathname && kern_path(pathname, 0, &path) == 0) {
  296. char *buf = tomoyo_realpath_from_path(&path);
  297. path_put(&path);
  298. return buf;
  299. }
  300. return NULL;
  301. }