1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * DFS referral cache routines
4 *
5 * Copyright (c) 2018-2019 Paulo Alcantara <palcantara@suse.de>
6 */
7
8 #include <linux/jhash.h>
9 #include <linux/ktime.h>
10 #include <linux/slab.h>
11 #include <linux/proc_fs.h>
12 #include <linux/nls.h>
13 #include <linux/workqueue.h>
14 #include <linux/uuid.h>
15 #include "cifsglob.h"
16 #include "smb2pdu.h"
17 #include "smb2proto.h"
18 #include "cifsproto.h"
19 #include "cifs_debug.h"
20 #include "cifs_unicode.h"
21 #include "smb2glob.h"
22 #include "dns_resolve.h"
23 #include "dfs.h"
24
25 #include "dfs_cache.h"
26
27 #define CACHE_HTABLE_SIZE 512
28 #define CACHE_MAX_ENTRIES 1024
29 #define CACHE_MIN_TTL 120 /* 2 minutes */
30 #define CACHE_DEFAULT_TTL 300 /* 5 minutes */
31
32 struct cache_dfs_tgt {
33 char *name;
34 int path_consumed;
35 struct list_head list;
36 };
37
38 struct cache_entry {
39 struct hlist_node hlist;
40 const char *path;
41 int hdr_flags; /* RESP_GET_DFS_REFERRAL.ReferralHeaderFlags */
42 int ttl; /* DFS_REREFERRAL_V3.TimeToLive */
43 int srvtype; /* DFS_REREFERRAL_V3.ServerType */
44 int ref_flags; /* DFS_REREFERRAL_V3.ReferralEntryFlags */
45 struct timespec64 etime;
46 int path_consumed; /* RESP_GET_DFS_REFERRAL.PathConsumed */
47 int numtgts;
48 struct list_head tlist;
49 struct cache_dfs_tgt *tgthint;
50 };
51
52 static struct kmem_cache *cache_slab __read_mostly;
53 struct workqueue_struct *dfscache_wq;
54
55 atomic_t dfs_cache_ttl;
56
57 static struct nls_table *cache_cp;
58
59 /*
60 * Number of entries in the cache
61 */
62 static atomic_t cache_count;
63
64 static struct hlist_head cache_htable[CACHE_HTABLE_SIZE];
65 static DECLARE_RWSEM(htable_rw_lock);
66
67 /**
68 * dfs_cache_canonical_path - get a canonical DFS path
69 *
70 * @path: DFS path
71 * @cp: codepage
72 * @remap: mapping type
73 *
74 * Return canonical path if success, otherwise error.
75 */
dfs_cache_canonical_path(const char * path,const struct nls_table * cp,int remap)76 char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap)
77 {
78 char *tmp;
79 int plen = 0;
80 char *npath;
81
82 if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/'))
83 return ERR_PTR(-EINVAL);
84
85 if (unlikely(strcmp(cp->charset, cache_cp->charset))) {
86 tmp = (char *)cifs_strndup_to_utf16(path, strlen(path), &plen, cp, remap);
87 if (!tmp) {
88 cifs_dbg(VFS, "%s: failed to convert path to utf16\n", __func__);
89 return ERR_PTR(-EINVAL);
90 }
91
92 npath = cifs_strndup_from_utf16(tmp, plen, true, cache_cp);
93 kfree(tmp);
94
95 if (!npath) {
96 cifs_dbg(VFS, "%s: failed to convert path from utf16\n", __func__);
97 return ERR_PTR(-EINVAL);
98 }
99 } else {
100 npath = kstrdup(path, GFP_KERNEL);
101 if (!npath)
102 return ERR_PTR(-ENOMEM);
103 }
104 convert_delimiter(npath, '\\');
105 return npath;
106 }
107
cache_entry_expired(const struct cache_entry * ce)108 static inline bool cache_entry_expired(const struct cache_entry *ce)
109 {
110 struct timespec64 ts;
111
112 ktime_get_coarse_real_ts64(&ts);
113 return timespec64_compare(&ts, &ce->etime) >= 0;
114 }
115
free_tgts(struct cache_entry * ce)116 static inline void free_tgts(struct cache_entry *ce)
117 {
118 struct cache_dfs_tgt *t, *n;
119
120 list_for_each_entry_safe(t, n, &ce->tlist, list) {
121 list_del(&t->list);
122 kfree(t->name);
123 kfree(t);
124 }
125
126 ce->numtgts = 0;
127 WRITE_ONCE(ce->tgthint, NULL);
128 }
129
flush_cache_ent(struct cache_entry * ce)130 static inline void flush_cache_ent(struct cache_entry *ce)
131 {
132 cifs_dbg(FYI, "%s: %s\n", __func__, ce->path);
133 hlist_del_init(&ce->hlist);
134 kfree(ce->path);
135 free_tgts(ce);
136 atomic_dec(&cache_count);
137 kmem_cache_free(cache_slab, ce);
138 }
139
flush_cache_ents(void)140 static void flush_cache_ents(void)
141 {
142 int i;
143
144 for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
145 struct hlist_head *l = &cache_htable[i];
146 struct hlist_node *n;
147 struct cache_entry *ce;
148
149 hlist_for_each_entry_safe(ce, n, l, hlist) {
150 if (!hlist_unhashed(&ce->hlist))
151 flush_cache_ent(ce);
152 }
153 }
154 }
155
156 /*
157 * dfs cache /proc file
158 */
dfscache_proc_show(struct seq_file * m,void * v)159 static int dfscache_proc_show(struct seq_file *m, void *v)
160 {
161 int i;
162 struct cache_entry *ce;
163 struct cache_dfs_tgt *t;
164
165 seq_puts(m, "DFS cache\n---------\n");
166
167 down_read(&htable_rw_lock);
168 for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
169 struct hlist_head *l = &cache_htable[i];
170
171 hlist_for_each_entry(ce, l, hlist) {
172 if (hlist_unhashed(&ce->hlist))
173 continue;
174
175 seq_printf(m,
176 "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n",
177 ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link",
178 ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags,
179 str_yes_no(DFS_INTERLINK(ce->hdr_flags)),
180 ce->path_consumed, str_yes_no(cache_entry_expired(ce)));
181
182 list_for_each_entry(t, &ce->tlist, list) {
183 seq_printf(m, " %s%s\n",
184 t->name,
185 READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
186 }
187 }
188 }
189 up_read(&htable_rw_lock);
190
191 return 0;
192 }
193
dfscache_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)194 static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer,
195 size_t count, loff_t *ppos)
196 {
197 char c;
198 int rc;
199
200 rc = get_user(c, buffer);
201 if (rc)
202 return rc;
203
204 if (c != '0')
205 return -EINVAL;
206
207 cifs_dbg(FYI, "clearing dfs cache\n");
208
209 down_write(&htable_rw_lock);
210 flush_cache_ents();
211 up_write(&htable_rw_lock);
212
213 return count;
214 }
215
dfscache_proc_open(struct inode * inode,struct file * file)216 static int dfscache_proc_open(struct inode *inode, struct file *file)
217 {
218 return single_open(file, dfscache_proc_show, NULL);
219 }
220
221 const struct proc_ops dfscache_proc_ops = {
222 .proc_open = dfscache_proc_open,
223 .proc_read = seq_read,
224 .proc_lseek = seq_lseek,
225 .proc_release = single_release,
226 .proc_write = dfscache_proc_write,
227 };
228
229 #ifdef CONFIG_CIFS_DEBUG2
dump_tgts(const struct cache_entry * ce)230 static inline void dump_tgts(const struct cache_entry *ce)
231 {
232 struct cache_dfs_tgt *t;
233
234 cifs_dbg(FYI, "target list:\n");
235 list_for_each_entry(t, &ce->tlist, list) {
236 cifs_dbg(FYI, " %s%s\n", t->name,
237 READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
238 }
239 }
240
dump_ce(const struct cache_entry * ce)241 static inline void dump_ce(const struct cache_entry *ce)
242 {
243 cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n",
244 ce->path,
245 ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl,
246 ce->etime.tv_nsec,
247 ce->hdr_flags, ce->ref_flags,
248 str_yes_no(DFS_INTERLINK(ce->hdr_flags)),
249 ce->path_consumed,
250 str_yes_no(cache_entry_expired(ce)));
251 dump_tgts(ce);
252 }
253
dump_refs(const struct dfs_info3_param * refs,int numrefs)254 static inline void dump_refs(const struct dfs_info3_param *refs, int numrefs)
255 {
256 int i;
257
258 cifs_dbg(FYI, "DFS referrals returned by the server:\n");
259 for (i = 0; i < numrefs; i++) {
260 const struct dfs_info3_param *ref = &refs[i];
261
262 cifs_dbg(FYI,
263 "\n"
264 "flags: 0x%x\n"
265 "path_consumed: %d\n"
266 "server_type: 0x%x\n"
267 "ref_flag: 0x%x\n"
268 "path_name: %s\n"
269 "node_name: %s\n"
270 "ttl: %d (%dm)\n",
271 ref->flags, ref->path_consumed, ref->server_type,
272 ref->ref_flag, ref->path_name, ref->node_name,
273 ref->ttl, ref->ttl / 60);
274 }
275 }
276 #else
277 #define dump_tgts(e)
278 #define dump_ce(e)
279 #define dump_refs(r, n)
280 #endif
281
282 /**
283 * dfs_cache_init - Initialize DFS referral cache.
284 *
285 * Return zero if initialized successfully, otherwise non-zero.
286 */
dfs_cache_init(void)287 int dfs_cache_init(void)
288 {
289 int rc;
290 int i;
291
292 dfscache_wq = alloc_workqueue("cifs-dfscache",
293 WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM,
294 0);
295 if (!dfscache_wq)
296 return -ENOMEM;
297
298 cache_slab = kmem_cache_create("cifs_dfs_cache",
299 sizeof(struct cache_entry), 0,
300 SLAB_HWCACHE_ALIGN, NULL);
301 if (!cache_slab) {
302 rc = -ENOMEM;
303 goto out_destroy_wq;
304 }
305
306 for (i = 0; i < CACHE_HTABLE_SIZE; i++)
307 INIT_HLIST_HEAD(&cache_htable[i]);
308
309 atomic_set(&cache_count, 0);
310 atomic_set(&dfs_cache_ttl, CACHE_DEFAULT_TTL);
311 cache_cp = load_nls("utf8");
312 if (!cache_cp)
313 cache_cp = load_nls_default();
314
315 cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__);
316 return 0;
317
318 out_destroy_wq:
319 destroy_workqueue(dfscache_wq);
320 return rc;
321 }
322
cache_entry_hash(const void * data,int size,unsigned int * hash)323 static int cache_entry_hash(const void *data, int size, unsigned int *hash)
324 {
325 int i, clen;
326 const unsigned char *s = data;
327 wchar_t c;
328 unsigned int h = 0;
329
330 for (i = 0; i < size; i += clen) {
331 clen = cache_cp->char2uni(&s[i], size - i, &c);
332 if (unlikely(clen < 0)) {
333 cifs_dbg(VFS, "%s: can't convert char\n", __func__);
334 return clen;
335 }
336 c = cifs_toupper(c);
337 h = jhash(&c, sizeof(c), h);
338 }
339 *hash = h % CACHE_HTABLE_SIZE;
340 return 0;
341 }
342
343 /* Return target hint of a DFS cache entry */
get_tgt_name(const struct cache_entry * ce)344 static inline char *get_tgt_name(const struct cache_entry *ce)
345 {
346 struct cache_dfs_tgt *t = READ_ONCE(ce->tgthint);
347
348 return t ? t->name : ERR_PTR(-ENOENT);
349 }
350
351 /* Return expire time out of a new entry's TTL */
get_expire_time(int ttl)352 static inline struct timespec64 get_expire_time(int ttl)
353 {
354 struct timespec64 ts = {
355 .tv_sec = ttl,
356 .tv_nsec = 0,
357 };
358 struct timespec64 now;
359
360 ktime_get_coarse_real_ts64(&now);
361 return timespec64_add(now, ts);
362 }
363
364 /* Allocate a new DFS target */
alloc_target(const char * name,int path_consumed)365 static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed)
366 {
367 struct cache_dfs_tgt *t;
368
369 t = kmalloc_obj(*t);
370 if (!t)
371 return ERR_PTR(-ENOMEM);
372 t->name = kstrdup(name, GFP_KERNEL);
373 if (!t->name) {
374 kfree(t);
375 return ERR_PTR(-ENOMEM);
376 }
377 t->path_consumed = path_consumed;
378 INIT_LIST_HEAD(&t->list);
379 return t;
380 }
381
382 /*
383 * Copy DFS referral information to a cache entry and conditionally update
384 * target hint.
385 */
copy_ref_data(const struct dfs_info3_param * refs,int numrefs,struct cache_entry * ce,const char * tgthint)386 static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
387 struct cache_entry *ce, const char *tgthint)
388 {
389 struct cache_dfs_tgt *target;
390 int i;
391
392 for (i = 0; i < numrefs; i++) {
393 struct cache_dfs_tgt *t;
394
395 t = alloc_target(refs[i].node_name, refs[i].path_consumed);
396 if (IS_ERR(t)) {
397 free_tgts(ce);
398 return PTR_ERR(t);
399 }
400 if (tgthint && !strcasecmp(t->name, tgthint)) {
401 list_add(&t->list, &ce->tlist);
402 tgthint = NULL;
403 } else {
404 list_add_tail(&t->list, &ce->tlist);
405 }
406 }
407
408 target = list_first_entry_or_null(&ce->tlist, struct cache_dfs_tgt,
409 list);
410
411 WRITE_ONCE(ce->tgthint, target);
412 ce->ttl = max_t(int, refs[0].ttl, CACHE_MIN_TTL);
413 ce->etime = get_expire_time(ce->ttl);
414 ce->srvtype = refs[0].server_type;
415 ce->hdr_flags = refs[0].flags;
416 ce->ref_flags = refs[0].ref_flag;
417 ce->path_consumed = refs[0].path_consumed;
418 ce->numtgts = numrefs;
419
420 return 0;
421 }
422
423 /* Allocate a new cache entry */
alloc_cache_entry(struct dfs_info3_param * refs,int numrefs)424 static struct cache_entry *alloc_cache_entry(struct dfs_info3_param *refs, int numrefs)
425 {
426 struct cache_entry *ce;
427 int rc;
428
429 ce = kmem_cache_zalloc(cache_slab, GFP_KERNEL);
430 if (!ce)
431 return ERR_PTR(-ENOMEM);
432
433 ce->path = refs[0].path_name;
434 refs[0].path_name = NULL;
435
436 INIT_HLIST_NODE(&ce->hlist);
437 INIT_LIST_HEAD(&ce->tlist);
438
439 rc = copy_ref_data(refs, numrefs, ce, NULL);
440 if (rc) {
441 kfree(ce->path);
442 kmem_cache_free(cache_slab, ce);
443 ce = ERR_PTR(rc);
444 }
445 return ce;
446 }
447
448 /* Remove all referrals that have a single target or oldest entry */
purge_cache(void)449 static void purge_cache(void)
450 {
451 int i;
452 struct cache_entry *ce;
453 struct cache_entry *oldest = NULL;
454
455 for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
456 struct hlist_head *l = &cache_htable[i];
457 struct hlist_node *n;
458
459 hlist_for_each_entry_safe(ce, n, l, hlist) {
460 if (hlist_unhashed(&ce->hlist))
461 continue;
462 if (ce->numtgts == 1)
463 flush_cache_ent(ce);
464 else if (!oldest ||
465 timespec64_compare(&ce->etime,
466 &oldest->etime) < 0)
467 oldest = ce;
468 }
469 }
470
471 if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES && oldest)
472 flush_cache_ent(oldest);
473 }
474
475 /* Add a new DFS cache entry */
add_cache_entry_locked(struct dfs_info3_param * refs,int numrefs)476 static struct cache_entry *add_cache_entry_locked(struct dfs_info3_param *refs,
477 int numrefs)
478 {
479 int rc;
480 struct cache_entry *ce;
481 unsigned int hash;
482 int ttl;
483
484 WARN_ON(!rwsem_is_locked(&htable_rw_lock));
485
486 if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) {
487 cifs_dbg(FYI, "%s: reached max cache size (%d)\n", __func__, CACHE_MAX_ENTRIES);
488 purge_cache();
489 }
490
491 rc = cache_entry_hash(refs[0].path_name, strlen(refs[0].path_name), &hash);
492 if (rc)
493 return ERR_PTR(rc);
494
495 ce = alloc_cache_entry(refs, numrefs);
496 if (IS_ERR(ce))
497 return ce;
498
499 ttl = min_t(int, atomic_read(&dfs_cache_ttl), ce->ttl);
500 atomic_set(&dfs_cache_ttl, ttl);
501
502 hlist_add_head(&ce->hlist, &cache_htable[hash]);
503 dump_ce(ce);
504
505 atomic_inc(&cache_count);
506
507 return ce;
508 }
509
510 /* Check if two DFS paths are equal. @s1 and @s2 are expected to be in @cache_cp's charset */
dfs_path_equal(const char * s1,int len1,const char * s2,int len2)511 static bool dfs_path_equal(const char *s1, int len1, const char *s2, int len2)
512 {
513 int i, l1, l2;
514 wchar_t c1, c2;
515
516 if (len1 != len2)
517 return false;
518
519 for (i = 0; i < len1; i += l1) {
520 l1 = cache_cp->char2uni(&s1[i], len1 - i, &c1);
521 l2 = cache_cp->char2uni(&s2[i], len2 - i, &c2);
522 if (unlikely(l1 < 0 && l2 < 0)) {
523 if (s1[i] != s2[i])
524 return false;
525 l1 = 1;
526 continue;
527 }
528 if (l1 != l2)
529 return false;
530 if (cifs_toupper(c1) != cifs_toupper(c2))
531 return false;
532 }
533 return true;
534 }
535
__lookup_cache_entry(const char * path,unsigned int hash,int len)536 static struct cache_entry *__lookup_cache_entry(const char *path, unsigned int hash, int len)
537 {
538 struct cache_entry *ce;
539
540 hlist_for_each_entry(ce, &cache_htable[hash], hlist) {
541 if (dfs_path_equal(ce->path, strlen(ce->path), path, len)) {
542 dump_ce(ce);
543 return ce;
544 }
545 }
546 return ERR_PTR(-ENOENT);
547 }
548
549 /*
550 * Find a DFS cache entry in hash table and optionally check prefix path against normalized @path.
551 *
552 * Use whole path components in the match. Must be called with htable_rw_lock held.
553 *
554 * Return cached entry if successful.
555 * Return ERR_PTR(-ENOENT) if the entry is not found.
556 * Return error ptr otherwise.
557 */
lookup_cache_entry(const char * path)558 static struct cache_entry *lookup_cache_entry(const char *path)
559 {
560 struct cache_entry *ce;
561 int cnt = 0;
562 const char *s = path, *e;
563 char sep = *s;
564 unsigned int hash;
565 int rc;
566
567 while ((s = strchr(s, sep)) && ++cnt < 3)
568 s++;
569
570 if (cnt < 3) {
571 rc = cache_entry_hash(path, strlen(path), &hash);
572 if (rc)
573 return ERR_PTR(rc);
574 return __lookup_cache_entry(path, hash, strlen(path));
575 }
576 /*
577 * Handle paths that have more than two path components and are a complete prefix of the DFS
578 * referral request path (@path).
579 *
580 * See MS-DFSC 3.2.5.5 "Receiving a Root Referral Request or Link Referral Request".
581 */
582 e = path + strlen(path) - 1;
583 while (e > s) {
584 int len;
585
586 /* skip separators */
587 while (e > s && *e == sep)
588 e--;
589 if (e == s)
590 break;
591
592 len = e + 1 - path;
593 rc = cache_entry_hash(path, len, &hash);
594 if (rc)
595 return ERR_PTR(rc);
596 ce = __lookup_cache_entry(path, hash, len);
597 if (!IS_ERR(ce))
598 return ce;
599
600 /* backward until separator */
601 while (e > s && *e != sep)
602 e--;
603 }
604 return ERR_PTR(-ENOENT);
605 }
606
607 /**
608 * dfs_cache_destroy - destroy DFS referral cache
609 */
dfs_cache_destroy(void)610 void dfs_cache_destroy(void)
611 {
612 unload_nls(cache_cp);
613 flush_cache_ents();
614 kmem_cache_destroy(cache_slab);
615 destroy_workqueue(dfscache_wq);
616
617 cifs_dbg(FYI, "%s: destroyed DFS referral cache\n", __func__);
618 }
619
620 /* Update a cache entry with the new referral in @refs */
update_cache_entry_locked(struct cache_entry * ce,const struct dfs_info3_param * refs,int numrefs)621 static int update_cache_entry_locked(struct cache_entry *ce, const struct dfs_info3_param *refs,
622 int numrefs)
623 {
624 struct cache_dfs_tgt *target;
625 char *th = NULL;
626 int rc;
627
628 WARN_ON(!rwsem_is_locked(&htable_rw_lock));
629
630 target = READ_ONCE(ce->tgthint);
631 if (target) {
632 th = kstrdup(target->name, GFP_KERNEL);
633 if (!th)
634 return -ENOMEM;
635 }
636
637 free_tgts(ce);
638
639 rc = copy_ref_data(refs, numrefs, ce, th);
640
641 kfree(th);
642
643 return rc;
644 }
645
get_dfs_referral(const unsigned int xid,struct cifs_ses * ses,const char * path,struct dfs_info3_param ** refs,int * numrefs)646 static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const char *path,
647 struct dfs_info3_param **refs, int *numrefs)
648 {
649 int rc;
650 int i;
651
652 *refs = NULL;
653 *numrefs = 0;
654
655 if (!ses || !ses->server || !ses->server->ops->get_dfs_refer)
656 return -EOPNOTSUPP;
657 if (unlikely(!cache_cp))
658 return -EINVAL;
659
660 cifs_dbg(FYI, "%s: ipc=%s referral=%s\n", __func__, ses->tcon_ipc->tree_name, path);
661 rc = ses->server->ops->get_dfs_refer(xid, ses, path, refs, numrefs, cache_cp,
662 NO_MAP_UNI_RSVD);
663 if (!rc) {
664 struct dfs_info3_param *ref = *refs;
665
666 for (i = 0; i < *numrefs; i++)
667 convert_delimiter(ref[i].path_name, '\\');
668 }
669 return rc;
670 }
671
672 /*
673 * Find, create or update a DFS cache entry.
674 *
675 * If the entry wasn't found, it will create a new one. Or if it was found but
676 * expired, then it will update the entry accordingly.
677 *
678 * For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
679 * handle them properly.
680 *
681 * On success, return entry with acquired lock for reading, otherwise error ptr.
682 */
cache_refresh_path(const unsigned int xid,struct cifs_ses * ses,const char * path,bool force_refresh)683 static struct cache_entry *cache_refresh_path(const unsigned int xid,
684 struct cifs_ses *ses,
685 const char *path,
686 bool force_refresh)
687 {
688 struct dfs_info3_param *refs = NULL;
689 struct cache_entry *ce;
690 int numrefs = 0;
691 int rc;
692
693 cifs_dbg(FYI, "%s: search path: %s\n", __func__, path);
694
695 down_read(&htable_rw_lock);
696
697 ce = lookup_cache_entry(path);
698 if (!IS_ERR(ce)) {
699 if (!force_refresh && !cache_entry_expired(ce))
700 return ce;
701 } else if (PTR_ERR(ce) != -ENOENT) {
702 up_read(&htable_rw_lock);
703 return ce;
704 }
705
706 /*
707 * Unlock shared access as we don't want to hold any locks while getting
708 * a new referral. The @ses used for performing the I/O could be
709 * reconnecting and it acquires @htable_rw_lock to look up the dfs cache
710 * in order to failover -- if necessary.
711 */
712 up_read(&htable_rw_lock);
713
714 /*
715 * Either the entry was not found, or it is expired, or it is a forced
716 * refresh.
717 * Request a new DFS referral in order to create or update a cache entry.
718 */
719 rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
720 if (rc) {
721 ce = ERR_PTR(rc);
722 goto out;
723 }
724
725 dump_refs(refs, numrefs);
726
727 down_write(&htable_rw_lock);
728 /* Re-check as another task might have it added or refreshed already */
729 ce = lookup_cache_entry(path);
730 if (!IS_ERR(ce)) {
731 if (force_refresh || cache_entry_expired(ce)) {
732 rc = update_cache_entry_locked(ce, refs, numrefs);
733 if (rc)
734 ce = ERR_PTR(rc);
735 }
736 } else if (PTR_ERR(ce) == -ENOENT) {
737 ce = add_cache_entry_locked(refs, numrefs);
738 }
739
740 if (IS_ERR(ce)) {
741 up_write(&htable_rw_lock);
742 goto out;
743 }
744
745 downgrade_write(&htable_rw_lock);
746 out:
747 free_dfs_info_array(refs, numrefs);
748 return ce;
749 }
750
751 /*
752 * Set up a DFS referral from a given cache entry.
753 *
754 * Must be called with htable_rw_lock held.
755 */
setup_referral(const char * path,struct cache_entry * ce,struct dfs_info3_param * ref,const char * target)756 static int setup_referral(const char *path, struct cache_entry *ce,
757 struct dfs_info3_param *ref, const char *target)
758 {
759 int rc;
760
761 cifs_dbg(FYI, "%s: set up new ref\n", __func__);
762
763 memset(ref, 0, sizeof(*ref));
764
765 ref->path_name = kstrdup(path, GFP_KERNEL);
766 if (!ref->path_name)
767 return -ENOMEM;
768
769 ref->node_name = kstrdup(target, GFP_KERNEL);
770 if (!ref->node_name) {
771 rc = -ENOMEM;
772 goto err_free_path;
773 }
774
775 ref->path_consumed = ce->path_consumed;
776 ref->ttl = ce->ttl;
777 ref->server_type = ce->srvtype;
778 ref->ref_flag = ce->ref_flags;
779 ref->flags = ce->hdr_flags;
780
781 return 0;
782
783 err_free_path:
784 kfree(ref->path_name);
785 ref->path_name = NULL;
786 return rc;
787 }
788
789 /* Return target list of a DFS cache entry */
get_targets(struct cache_entry * ce,struct dfs_cache_tgt_list * tl)790 static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
791 {
792 int rc;
793 struct list_head *head = &tl->tl_list;
794 struct cache_dfs_tgt *t;
795 struct dfs_cache_tgt_iterator *it, *nit;
796
797 memset(tl, 0, sizeof(*tl));
798 INIT_LIST_HEAD(head);
799
800 list_for_each_entry(t, &ce->tlist, list) {
801 it = kzalloc_obj(*it, GFP_ATOMIC);
802 if (!it) {
803 rc = -ENOMEM;
804 goto err_free_it;
805 }
806
807 it->it_name = kstrdup(t->name, GFP_ATOMIC);
808 if (!it->it_name) {
809 kfree(it);
810 rc = -ENOMEM;
811 goto err_free_it;
812 }
813 it->it_path_consumed = t->path_consumed;
814
815 if (READ_ONCE(ce->tgthint) == t)
816 list_add(&it->it_list, head);
817 else
818 list_add_tail(&it->it_list, head);
819 }
820
821 tl->tl_numtgts = ce->numtgts;
822
823 return 0;
824
825 err_free_it:
826 list_for_each_entry_safe(it, nit, head, it_list) {
827 list_del(&it->it_list);
828 kfree(it->it_name);
829 kfree(it);
830 }
831 return rc;
832 }
833
834 /**
835 * dfs_cache_find - find a DFS cache entry
836 *
837 * If it doesn't find the cache entry, then it will get a DFS referral
838 * for @path and create a new entry.
839 *
840 * In case the cache entry exists but expired, it will get a DFS referral
841 * for @path and then update the respective cache entry.
842 *
843 * These parameters are passed down to the get_dfs_refer() call if it
844 * needs to be issued:
845 * @xid: syscall xid
846 * @ses: smb session to issue the request on
847 * @cp: codepage
848 * @remap: path character remapping type
849 * @path: path to lookup in DFS referral cache.
850 *
851 * @ref: when non-NULL, store single DFS referral result in it.
852 * @tgt_list: when non-NULL, store complete DFS target list in it.
853 *
854 * Return zero if the target was found, otherwise non-zero.
855 */
dfs_cache_find(const unsigned int xid,struct cifs_ses * ses,const struct nls_table * cp,int remap,const char * path,struct dfs_info3_param * ref,struct dfs_cache_tgt_list * tgt_list)856 int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *cp,
857 int remap, const char *path, struct dfs_info3_param *ref,
858 struct dfs_cache_tgt_list *tgt_list)
859 {
860 int rc;
861 const char *npath;
862 struct cache_entry *ce;
863
864 npath = dfs_cache_canonical_path(path, cp, remap);
865 if (IS_ERR(npath))
866 return PTR_ERR(npath);
867
868 ce = cache_refresh_path(xid, ses, npath, false);
869 if (IS_ERR(ce)) {
870 rc = PTR_ERR(ce);
871 goto out_free_path;
872 }
873
874 if (ref) {
875 char *target = get_tgt_name(ce);
876
877 if (IS_ERR(target)) {
878 rc = PTR_ERR(target);
879 goto out_unlock;
880 }
881 rc = setup_referral(path, ce, ref, target);
882 } else {
883 rc = 0;
884 }
885
886 if (!rc && tgt_list)
887 rc = get_targets(ce, tgt_list);
888
889 out_unlock:
890 up_read(&htable_rw_lock);
891
892 out_free_path:
893 kfree(npath);
894 return rc;
895 }
896
897 /**
898 * dfs_cache_noreq_find - find a DFS cache entry without sending any requests to
899 * the currently connected server.
900 *
901 * NOTE: This function will neither update a cache entry in case it was
902 * expired, nor create a new cache entry if @path hasn't been found. It heavily
903 * relies on an existing cache entry.
904 *
905 * @path: canonical DFS path to lookup in the DFS referral cache.
906 * @ref: when non-NULL, store single DFS referral result in it.
907 * @tgt_list: when non-NULL, store complete DFS target list in it.
908 *
909 * Return 0 if successful.
910 * Return -ENOENT if the entry was not found.
911 * Return non-zero for other errors.
912 */
dfs_cache_noreq_find(const char * path,struct dfs_info3_param * ref,struct dfs_cache_tgt_list * tgt_list)913 int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
914 struct dfs_cache_tgt_list *tgt_list)
915 {
916 int rc;
917 struct cache_entry *ce;
918
919 cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
920
921 down_read(&htable_rw_lock);
922
923 ce = lookup_cache_entry(path);
924 if (IS_ERR(ce)) {
925 rc = PTR_ERR(ce);
926 goto out_unlock;
927 }
928
929 if (ref) {
930 char *target = get_tgt_name(ce);
931
932 if (IS_ERR(target)) {
933 rc = PTR_ERR(target);
934 goto out_unlock;
935 }
936 rc = setup_referral(path, ce, ref, target);
937 } else {
938 rc = 0;
939 }
940 if (!rc && tgt_list)
941 rc = get_targets(ce, tgt_list);
942
943 out_unlock:
944 up_read(&htable_rw_lock);
945 return rc;
946 }
947
948 /**
949 * dfs_cache_noreq_update_tgthint - update target hint of a DFS cache entry
950 * without sending any requests to the currently connected server.
951 *
952 * NOTE: This function will neither update a cache entry in case it was
953 * expired, nor create a new cache entry if @path hasn't been found. It heavily
954 * relies on an existing cache entry.
955 *
956 * @path: canonical DFS path to lookup in DFS referral cache.
957 * @it: target iterator which contains the target hint to update the cache
958 * entry with.
959 *
960 * Return zero if the target hint was updated successfully, otherwise non-zero.
961 */
dfs_cache_noreq_update_tgthint(const char * path,const struct dfs_cache_tgt_iterator * it)962 void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it)
963 {
964 struct cache_dfs_tgt *t;
965 struct cache_entry *ce;
966
967 if (!path || !it)
968 return;
969
970 cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
971
972 down_read(&htable_rw_lock);
973
974 ce = lookup_cache_entry(path);
975 if (IS_ERR(ce))
976 goto out_unlock;
977
978 t = READ_ONCE(ce->tgthint);
979
980 /* Check 't' in case ce->tgthint was cleared by free_tgts() */
981 if (t && unlikely(!strcasecmp(it->it_name, t->name)))
982 goto out_unlock;
983
984 list_for_each_entry(t, &ce->tlist, list) {
985 if (!strcasecmp(t->name, it->it_name)) {
986 WRITE_ONCE(ce->tgthint, t);
987 cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
988 it->it_name);
989 break;
990 }
991 }
992
993 out_unlock:
994 up_read(&htable_rw_lock);
995 }
996
997 /**
998 * dfs_cache_get_tgt_referral - returns a DFS referral (@ref) from a given
999 * target iterator (@it).
1000 *
1001 * @path: canonical DFS path to lookup in DFS referral cache.
1002 * @it: DFS target iterator.
1003 * @ref: DFS referral pointer to set up the gathered information.
1004 *
1005 * Return zero if the DFS referral was set up correctly, otherwise non-zero.
1006 */
dfs_cache_get_tgt_referral(const char * path,const struct dfs_cache_tgt_iterator * it,struct dfs_info3_param * ref)1007 int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
1008 struct dfs_info3_param *ref)
1009 {
1010 int rc;
1011 struct cache_entry *ce;
1012
1013 if (!it || !ref)
1014 return -EINVAL;
1015
1016 cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
1017
1018 down_read(&htable_rw_lock);
1019
1020 ce = lookup_cache_entry(path);
1021 if (IS_ERR(ce)) {
1022 rc = PTR_ERR(ce);
1023 goto out_unlock;
1024 }
1025
1026 cifs_dbg(FYI, "%s: target name: %s\n", __func__, it->it_name);
1027
1028 rc = setup_referral(path, ce, ref, it->it_name);
1029
1030 out_unlock:
1031 up_read(&htable_rw_lock);
1032 return rc;
1033 }
1034
1035 /* Extract share from DFS target and return a pointer to prefix path or NULL */
parse_target_share(const char * target,char ** share)1036 static const char *parse_target_share(const char *target, char **share)
1037 {
1038 const char *s, *seps = "/\\";
1039 size_t len;
1040
1041 s = strpbrk(target + 1, seps);
1042 if (!s)
1043 return ERR_PTR(-EINVAL);
1044
1045 len = strcspn(s + 1, seps);
1046 if (!len)
1047 return ERR_PTR(-EINVAL);
1048 s += len;
1049
1050 len = s - target + 1;
1051 *share = kstrndup(target, len, GFP_KERNEL);
1052 if (!*share)
1053 return ERR_PTR(-ENOMEM);
1054
1055 s = target + len;
1056 return s + strspn(s, seps);
1057 }
1058
1059 /**
1060 * dfs_cache_get_tgt_share - parse a DFS target
1061 *
1062 * @path: DFS full path
1063 * @it: DFS target iterator.
1064 * @share: tree name.
1065 * @prefix: prefix path.
1066 *
1067 * Return zero if target was parsed correctly, otherwise non-zero.
1068 */
dfs_cache_get_tgt_share(char * path,const struct dfs_cache_tgt_iterator * it,char ** share,char ** prefix)1069 int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
1070 char **prefix)
1071 {
1072 char sep;
1073 char *target_share;
1074 char *ppath = NULL;
1075 const char *target_ppath, *dfsref_ppath;
1076 size_t target_pplen, dfsref_pplen;
1077 size_t len, c;
1078
1079 if (!it || !path || !share || !prefix || strlen(path) < it->it_path_consumed)
1080 return -EINVAL;
1081
1082 sep = it->it_name[0];
1083 if (sep != '\\' && sep != '/')
1084 return -EINVAL;
1085
1086 target_ppath = parse_target_share(it->it_name, &target_share);
1087 if (IS_ERR(target_ppath))
1088 return PTR_ERR(target_ppath);
1089
1090 /* point to prefix in DFS referral path */
1091 dfsref_ppath = path + it->it_path_consumed;
1092 dfsref_ppath += strspn(dfsref_ppath, "/\\");
1093
1094 target_pplen = strlen(target_ppath);
1095 dfsref_pplen = strlen(dfsref_ppath);
1096
1097 /* merge prefix paths from DFS referral path and target node */
1098 if (target_pplen || dfsref_pplen) {
1099 len = target_pplen + dfsref_pplen + 2;
1100 ppath = kzalloc(len, GFP_KERNEL);
1101 if (!ppath) {
1102 kfree(target_share);
1103 return -ENOMEM;
1104 }
1105 c = strscpy(ppath, target_ppath, len);
1106 if (c && dfsref_pplen)
1107 ppath[c] = sep;
1108 strlcat(ppath, dfsref_ppath, len);
1109 }
1110 *share = target_share;
1111 *prefix = ppath;
1112 return 0;
1113 }
1114
target_share_equal(struct cifs_tcon * tcon,const char * s1)1115 static bool target_share_equal(struct cifs_tcon *tcon, const char *s1)
1116 {
1117 struct TCP_Server_Info *server = tcon->ses->server;
1118 const char *s2 = &tcon->tree_name[1];
1119 struct sockaddr_storage ss;
1120 bool match;
1121 int rc;
1122
1123 if (strcasecmp(s2, s1))
1124 return false;
1125
1126 /*
1127 * Resolve share's hostname and check if server address matches. Otherwise just ignore it
1128 * as we could not have upcall to resolve hostname or failed to convert ip address.
1129 */
1130 rc = dns_resolve_unc(server->dns_dom, s1, (struct sockaddr *)&ss);
1131 if (rc < 0)
1132 return true;
1133
1134 cifs_server_lock(server);
1135 match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
1136 cifs_dbg(FYI, "%s: [share=%s] ipaddr matched: %s\n", __func__, s1, str_yes_no(match));
1137 cifs_server_unlock(server);
1138
1139 return match;
1140 }
1141
is_ses_good(struct cifs_tcon * tcon,struct cifs_ses * ses)1142 static bool is_ses_good(struct cifs_tcon *tcon, struct cifs_ses *ses)
1143 {
1144 struct TCP_Server_Info *server = ses->server;
1145 struct cifs_tcon *ipc = NULL;
1146 bool ret;
1147
1148 spin_lock(&cifs_tcp_ses_lock);
1149 spin_lock(&ses->ses_lock);
1150 spin_lock(&ses->chan_lock);
1151
1152 ret = !cifs_chan_needs_reconnect(ses, server) &&
1153 ses->ses_status == SES_GOOD;
1154
1155 spin_unlock(&ses->chan_lock);
1156
1157 if (!ret)
1158 goto out;
1159
1160 if (likely(ses->tcon_ipc)) {
1161 if (ses->tcon_ipc->need_reconnect) {
1162 ret = false;
1163 goto out;
1164 }
1165 } else {
1166 spin_unlock(&ses->ses_lock);
1167 spin_unlock(&cifs_tcp_ses_lock);
1168
1169 ipc = cifs_setup_ipc(ses, tcon->seal);
1170
1171 spin_lock(&cifs_tcp_ses_lock);
1172 spin_lock(&ses->ses_lock);
1173 if (!IS_ERR(ipc)) {
1174 if (!ses->tcon_ipc) {
1175 ses->tcon_ipc = ipc;
1176 ipc = NULL;
1177 }
1178 } else {
1179 ret = false;
1180 ipc = NULL;
1181 }
1182 }
1183
1184 out:
1185 spin_unlock(&ses->ses_lock);
1186 spin_unlock(&cifs_tcp_ses_lock);
1187 if (ipc && server->ops->tree_disconnect) {
1188 unsigned int xid = get_xid();
1189
1190 (void)server->ops->tree_disconnect(xid, ipc);
1191 _free_xid(xid);
1192 }
1193 tconInfoFree(ipc, netfs_trace_tcon_ref_free_ipc);
1194 return ret;
1195 }
1196
1197 /* Refresh dfs referral of @ses */
refresh_ses_referral(struct cifs_tcon * tcon,struct cifs_ses * ses)1198 static void refresh_ses_referral(struct cifs_tcon *tcon, struct cifs_ses *ses)
1199 {
1200 struct cache_entry *ce;
1201 unsigned int xid;
1202 const char *path;
1203 int rc = 0;
1204
1205 xid = get_xid();
1206
1207 path = dfs_ses_refpath(ses);
1208 if (IS_ERR(path)) {
1209 rc = PTR_ERR(path);
1210 goto out;
1211 }
1212
1213 ses = CIFS_DFS_ROOT_SES(ses);
1214 if (!is_ses_good(tcon, ses)) {
1215 cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n",
1216 __func__);
1217 goto out;
1218 }
1219
1220 ce = cache_refresh_path(xid, ses, path, false);
1221 if (!IS_ERR(ce))
1222 up_read(&htable_rw_lock);
1223 else
1224 rc = PTR_ERR(ce);
1225
1226 out:
1227 free_xid(xid);
1228 }
1229
__refresh_tcon_referral(struct cifs_tcon * tcon,const char * path,struct dfs_info3_param * refs,int numrefs,bool force_refresh)1230 static int __refresh_tcon_referral(struct cifs_tcon *tcon,
1231 const char *path,
1232 struct dfs_info3_param *refs,
1233 int numrefs, bool force_refresh)
1234 {
1235 struct cache_entry *ce;
1236 bool reconnect = force_refresh;
1237 int rc = 0;
1238 int i;
1239
1240 if (unlikely(!numrefs))
1241 return 0;
1242
1243 if (force_refresh) {
1244 for (i = 0; i < numrefs; i++) {
1245 /* TODO: include prefix paths in the matching */
1246 if (target_share_equal(tcon, refs[i].node_name)) {
1247 reconnect = false;
1248 break;
1249 }
1250 }
1251 }
1252
1253 down_write(&htable_rw_lock);
1254 ce = lookup_cache_entry(path);
1255 if (!IS_ERR(ce)) {
1256 if (force_refresh || cache_entry_expired(ce))
1257 rc = update_cache_entry_locked(ce, refs, numrefs);
1258 } else if (PTR_ERR(ce) == -ENOENT) {
1259 ce = add_cache_entry_locked(refs, numrefs);
1260 }
1261 up_write(&htable_rw_lock);
1262
1263 if (IS_ERR(ce))
1264 rc = PTR_ERR(ce);
1265 if (reconnect) {
1266 cifs_tcon_dbg(FYI, "%s: mark for reconnect\n", __func__);
1267 cifs_signal_cifsd_for_reconnect(tcon->ses->server, true);
1268 }
1269 return rc;
1270 }
1271
refresh_tcon_referral(struct cifs_tcon * tcon,bool force_refresh)1272 static void refresh_tcon_referral(struct cifs_tcon *tcon, bool force_refresh)
1273 {
1274 struct dfs_info3_param *refs = NULL;
1275 struct cache_entry *ce;
1276 struct cifs_ses *ses;
1277 bool needs_refresh;
1278 const char *path;
1279 unsigned int xid;
1280 int numrefs = 0;
1281 int rc = 0;
1282
1283 xid = get_xid();
1284 ses = tcon->ses;
1285
1286 path = dfs_ses_refpath(ses);
1287 if (IS_ERR(path)) {
1288 rc = PTR_ERR(path);
1289 goto out;
1290 }
1291
1292 down_read(&htable_rw_lock);
1293 ce = lookup_cache_entry(path);
1294 needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce);
1295 if (!needs_refresh) {
1296 up_read(&htable_rw_lock);
1297 goto out;
1298 }
1299 up_read(&htable_rw_lock);
1300
1301 ses = CIFS_DFS_ROOT_SES(ses);
1302 if (!is_ses_good(tcon, ses)) {
1303 cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n",
1304 __func__);
1305 goto out;
1306 }
1307
1308 rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
1309 if (!rc) {
1310 rc = __refresh_tcon_referral(tcon, path, refs,
1311 numrefs, force_refresh);
1312 }
1313
1314 out:
1315 free_xid(xid);
1316 free_dfs_info_array(refs, numrefs);
1317 }
1318
1319 /**
1320 * dfs_cache_remount_fs - remount a DFS share
1321 *
1322 * Reconfigure dfs mount by forcing a new DFS referral and if the currently cached targets do not
1323 * match any of the new targets, mark it for reconnect.
1324 *
1325 * @cifs_sb: cifs superblock.
1326 *
1327 * Return zero if remounted, otherwise non-zero.
1328 */
dfs_cache_remount_fs(struct cifs_sb_info * cifs_sb)1329 int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
1330 {
1331 struct cifs_tcon *tcon;
1332
1333 if (!cifs_sb || !cifs_sb->master_tlink)
1334 return -EINVAL;
1335
1336 tcon = cifs_sb_master_tcon(cifs_sb);
1337
1338 spin_lock(&tcon->tc_lock);
1339 if (!tcon->origin_fullpath) {
1340 spin_unlock(&tcon->tc_lock);
1341 cifs_dbg(FYI, "%s: not a dfs mount\n", __func__);
1342 return 0;
1343 }
1344 spin_unlock(&tcon->tc_lock);
1345
1346 /*
1347 * After reconnecting to a different server, unique ids won't match anymore, so we disable
1348 * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE).
1349 */
1350 cifs_autodisable_serverino(cifs_sb, "DFS failover may potentially connect to a different server, inode numbers won't match anymore", 0);
1351 /*
1352 * Force the use of prefix path to support failover on DFS paths that resolve to targets
1353 * that have different prefix paths.
1354 */
1355 atomic_or(CIFS_MOUNT_USE_PREFIX_PATH, &cifs_sb->mnt_cifs_flags);
1356
1357 refresh_tcon_referral(tcon, true);
1358 return 0;
1359 }
1360
1361 /* Refresh all DFS referrals related to DFS tcon */
dfs_cache_refresh(struct work_struct * work)1362 void dfs_cache_refresh(struct work_struct *work)
1363 {
1364 struct cifs_tcon *tcon;
1365 struct cifs_ses *ses;
1366
1367 tcon = container_of(work, struct cifs_tcon, dfs_cache_work.work);
1368
1369 list_for_each_entry(ses, &tcon->dfs_ses_list, dlist)
1370 refresh_ses_referral(tcon, ses);
1371 refresh_tcon_referral(tcon, false);
1372
1373 queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,
1374 atomic_read(&dfs_cache_ttl) * HZ);
1375 }
1376