realpath.c 7.4 KB

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