namespace.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Contains mounting routines used for handling traversal via SMB junctions.
  4. *
  5. * Copyright (c) 2007 Igor Mammedov
  6. * Copyright (C) International Business Machines Corp., 2008
  7. * Author(s): Igor Mammedov (niallain@gmail.com)
  8. * Steve French (sfrench@us.ibm.com)
  9. * Copyright (c) 2023 Paulo Alcantara <palcantara@suse.de>
  10. */
  11. #include <linux/dcache.h>
  12. #include <linux/mount.h>
  13. #include <linux/namei.h>
  14. #include <linux/slab.h>
  15. #include <linux/vfs.h>
  16. #include <linux/fs.h>
  17. #include <linux/inet.h>
  18. #include "cifsglob.h"
  19. #include "cifsproto.h"
  20. #include "cifsfs.h"
  21. #include "cifs_debug.h"
  22. #include "fs_context.h"
  23. static LIST_HEAD(cifs_automount_list);
  24. static void cifs_expire_automounts(struct work_struct *work);
  25. static DECLARE_DELAYED_WORK(cifs_automount_task,
  26. cifs_expire_automounts);
  27. static int cifs_mountpoint_expiry_timeout = 500 * HZ;
  28. static void cifs_expire_automounts(struct work_struct *work)
  29. {
  30. struct list_head *list = &cifs_automount_list;
  31. mark_mounts_for_expiry(list);
  32. if (!list_empty(list))
  33. schedule_delayed_work(&cifs_automount_task,
  34. cifs_mountpoint_expiry_timeout);
  35. }
  36. void cifs_release_automount_timer(void)
  37. {
  38. if (WARN_ON(!list_empty(&cifs_automount_list)))
  39. return;
  40. cancel_delayed_work_sync(&cifs_automount_task);
  41. }
  42. /**
  43. * cifs_build_devname - build a devicename from a UNC and optional prepath
  44. * @nodename: pointer to UNC string
  45. * @prepath: pointer to prefixpath (or NULL if there isn't one)
  46. *
  47. * Build a new cifs devicename after chasing a DFS referral. Allocate a buffer
  48. * big enough to hold the final thing. Copy the UNC from the nodename, and
  49. * concatenate the prepath onto the end of it if there is one.
  50. *
  51. * Returns pointer to the built string, or a ERR_PTR. Caller is responsible
  52. * for freeing the returned string.
  53. */
  54. char *
  55. cifs_build_devname(char *nodename, const char *prepath)
  56. {
  57. size_t pplen;
  58. size_t unclen;
  59. char *dev;
  60. char *pos;
  61. /* skip over any preceding delimiters */
  62. nodename += strspn(nodename, "\\");
  63. if (!*nodename)
  64. return ERR_PTR(-EINVAL);
  65. /* get length of UNC and set pos to last char */
  66. unclen = strlen(nodename);
  67. pos = nodename + unclen - 1;
  68. /* trim off any trailing delimiters */
  69. while (*pos == '\\') {
  70. --pos;
  71. --unclen;
  72. }
  73. /* allocate a buffer:
  74. * +2 for preceding "//"
  75. * +1 for delimiter between UNC and prepath
  76. * +1 for trailing NULL
  77. */
  78. pplen = prepath ? strlen(prepath) : 0;
  79. dev = kmalloc(2 + unclen + 1 + pplen + 1, GFP_KERNEL);
  80. if (!dev)
  81. return ERR_PTR(-ENOMEM);
  82. pos = dev;
  83. /* add the initial "//" */
  84. *pos = '/';
  85. ++pos;
  86. *pos = '/';
  87. ++pos;
  88. /* copy in the UNC portion from referral */
  89. memcpy(pos, nodename, unclen);
  90. pos += unclen;
  91. /* copy the prefixpath remainder (if there is one) */
  92. if (pplen) {
  93. *pos = '/';
  94. ++pos;
  95. memcpy(pos, prepath, pplen);
  96. pos += pplen;
  97. }
  98. /* NULL terminator */
  99. *pos = '\0';
  100. convert_delimiter(dev, '/');
  101. return dev;
  102. }
  103. static bool is_dfs_mount(struct dentry *dentry)
  104. {
  105. struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
  106. struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
  107. bool ret;
  108. spin_lock(&tcon->tc_lock);
  109. ret = !!tcon->origin_fullpath;
  110. spin_unlock(&tcon->tc_lock);
  111. return ret;
  112. }
  113. /* Return full path out of a dentry set for automount */
  114. static char *automount_fullpath(struct dentry *dentry, void *page)
  115. {
  116. struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
  117. struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
  118. size_t len;
  119. char *s;
  120. spin_lock(&tcon->tc_lock);
  121. if (!tcon->origin_fullpath) {
  122. spin_unlock(&tcon->tc_lock);
  123. return build_path_from_dentry_optional_prefix(dentry,
  124. page,
  125. true);
  126. }
  127. spin_unlock(&tcon->tc_lock);
  128. if (unlikely(!page))
  129. return ERR_PTR(-ENOMEM);
  130. s = dentry_path_raw(dentry, page, PATH_MAX);
  131. if (IS_ERR(s))
  132. return s;
  133. /* for root, we want "" */
  134. if (!s[1])
  135. s++;
  136. spin_lock(&tcon->tc_lock);
  137. len = strlen(tcon->origin_fullpath);
  138. if (s < (char *)page + len) {
  139. spin_unlock(&tcon->tc_lock);
  140. return ERR_PTR(-ENAMETOOLONG);
  141. }
  142. s -= len;
  143. memcpy(s, tcon->origin_fullpath, len);
  144. spin_unlock(&tcon->tc_lock);
  145. convert_delimiter(s, '/');
  146. return s;
  147. }
  148. static void fs_context_set_ids(struct smb3_fs_context *ctx)
  149. {
  150. kuid_t uid = current_fsuid();
  151. kgid_t gid = current_fsgid();
  152. if (ctx->multiuser) {
  153. if (!ctx->uid_specified)
  154. ctx->linux_uid = uid;
  155. if (!ctx->gid_specified)
  156. ctx->linux_gid = gid;
  157. }
  158. if (!ctx->cruid_specified)
  159. ctx->cred_uid = uid;
  160. }
  161. /*
  162. * Create a vfsmount that we can automount
  163. */
  164. static struct vfsmount *cifs_do_automount(struct path *path)
  165. {
  166. int rc;
  167. struct dentry *mntpt = path->dentry;
  168. struct fs_context *fc;
  169. void *page = NULL;
  170. struct smb3_fs_context *ctx, *cur_ctx;
  171. struct smb3_fs_context tmp;
  172. char *full_path;
  173. struct vfsmount *mnt;
  174. struct cifs_sb_info *mntpt_sb;
  175. struct cifs_ses *ses;
  176. if (IS_ROOT(mntpt))
  177. return ERR_PTR(-ESTALE);
  178. mntpt_sb = CIFS_SB(mntpt->d_sb);
  179. ses = cifs_sb_master_tcon(mntpt_sb)->ses;
  180. cur_ctx = mntpt_sb->ctx;
  181. /*
  182. * At this point, the root session should be in the mntpt sb. We should
  183. * bring the sb context passwords in sync with the root session's
  184. * passwords. This would help prevent unnecessary retries and password
  185. * swaps for automounts.
  186. */
  187. mutex_lock(&ses->session_mutex);
  188. rc = smb3_sync_session_ctx_passwords(mntpt_sb, ses);
  189. mutex_unlock(&ses->session_mutex);
  190. if (rc)
  191. return ERR_PTR(rc);
  192. fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, mntpt);
  193. if (IS_ERR(fc))
  194. return ERR_CAST(fc);
  195. ctx = smb3_fc2context(fc);
  196. page = alloc_dentry_path();
  197. full_path = automount_fullpath(mntpt, page);
  198. if (IS_ERR(full_path)) {
  199. mnt = ERR_CAST(full_path);
  200. goto out;
  201. }
  202. tmp = *cur_ctx;
  203. tmp.source = NULL;
  204. tmp.leaf_fullpath = NULL;
  205. tmp.UNC = tmp.prepath = NULL;
  206. tmp.dfs_root_ses = NULL;
  207. fs_context_set_ids(&tmp);
  208. rc = smb3_fs_context_dup(ctx, &tmp);
  209. if (rc) {
  210. mnt = ERR_PTR(rc);
  211. goto out;
  212. }
  213. rc = smb3_parse_devname(full_path, ctx);
  214. if (rc) {
  215. mnt = ERR_PTR(rc);
  216. goto out;
  217. }
  218. ctx->source = smb3_fs_context_fullpath(ctx, '/');
  219. if (IS_ERR(ctx->source)) {
  220. mnt = ERR_CAST(ctx->source);
  221. ctx->source = NULL;
  222. goto out;
  223. }
  224. ctx->dfs_automount = ctx->dfs_conn = is_dfs_mount(mntpt);
  225. cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dfs_automount=%d\n",
  226. __func__, ctx->source, ctx->UNC, ctx->prepath, ctx->dfs_automount);
  227. mnt = fc_mount(fc);
  228. out:
  229. put_fs_context(fc);
  230. free_dentry_path(page);
  231. return mnt;
  232. }
  233. /*
  234. * Attempt to automount the referral
  235. */
  236. struct vfsmount *cifs_d_automount(struct path *path)
  237. {
  238. struct vfsmount *newmnt;
  239. cifs_dbg(FYI, "%s: %pd\n", __func__, path->dentry);
  240. newmnt = cifs_do_automount(path);
  241. if (IS_ERR(newmnt)) {
  242. cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
  243. return newmnt;
  244. }
  245. mntget(newmnt); /* prevent immediate expiration */
  246. mnt_set_expiry(newmnt, &cifs_automount_list);
  247. schedule_delayed_work(&cifs_automount_task,
  248. cifs_mountpoint_expiry_timeout);
  249. cifs_dbg(FYI, "leaving %s [ok]\n" , __func__);
  250. return newmnt;
  251. }
  252. const struct inode_operations cifs_namespace_inode_operations = {
  253. };