realpath.c 8.0 KB

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