History

Merge tag '6.6-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client updates from Steve French: - fixes for excessive stack usage - multichannel reconnect improvements - DFS fix and cleanup patches - move UCS-2 conversion code to fs/nls and update cifs and jfs to use them - cleanup patch for compounding, one to fix confusing function name - inode number collision fix - reparse point fixes (including avoiding an extra unneeded query on symlinks) and a minor cleanup - directory lease (caching) improvement * tag '6.6-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: (24 commits) fs/jfs: Use common ucs2 upper case table fs/smb/client: Use common code in client fs/smb: Swing unicode common code from smb->NLS fs/smb: Remove unicode 'lower' tables SMB3: rename macro CIFS_SERVER_IS_CHAN to avoid confusion [SMB3] send channel sequence number in SMB3 requests after reconnects cifs: update desired access while requesting for directory lease smb: client: reduce stack usage in smb2_query_reparse_point() smb: client: reduce stack usage in smb2_query_info_compound() smb: client: reduce stack usage in smb2_set_ea() smb: client: reduce stack usage in smb_send_rqst() smb: client: reduce stack usage in cifs_demultiplex_thread() smb: client: reduce stack usage in cifs_try_adding_channels() smb: cilent: set reparse mount points as automounts smb: client: query reparse points in older dialects smb: client: do not query reparse points twice on symlinks smb: client: parse reparse point flag in create response smb: client: get rid of dfs code dep in namespace.c smb: client: get rid of dfs naming in automount code smb: client: rename cifs_dfs_ref.c to namespace.c ...

Linus Torvalds committed 3 years ago

Commit b97d64c2 parents 47d154e f3a9b3743 files · +1377 −2021Browse files

Unified · Split

43 files
  1. fs/jfs/Kconfig +1 −0
  2. fs/jfs/Makefile +1 −1
  3. fs/jfs/jfs_unicode.h +5 −12
  4. fs/jfs/jfs_uniupr.c +0 −121
  5. fs/nls/Kconfig +8 −0
  6. fs/nls/Makefile +1 −0
  7. fs/nls/nls_ucs2_data.h +15 −0
  8. fs/nls/nls_ucs2_utils.c +17 −139
  9. fs/nls/nls_ucs2_utils.h +285 −0
  10. fs/smb/client/Kconfig +1 −0
  11. fs/smb/client/Makefile +3 −2
  12. fs/smb/client/cached_dir.c +1 −1
  13. fs/smb/client/cifs_debug.c +1 −1
  14. fs/smb/client/cifs_unicode.c +0 −1
  15. fs/smb/client/cifs_unicode.h +1 −329
  16. fs/smb/client/cifs_uniupr.h +0 −239
  17. fs/smb/client/cifsfs.c +1 −1
  18. fs/smb/client/cifsfs.h +2 −9
  19. fs/smb/client/cifsglob.h +58 −14
  20. fs/smb/client/cifsproto.h +4 −5
  21. fs/smb/client/connect.c +11 −10
  22. fs/smb/client/dfs.c +150 −121
  23. fs/smb/client/dfs.h +104 −37
  24. fs/smb/client/dfs_cache.c +4 −6
  25. fs/smb/client/dfs_cache.h +8 −4
  26. fs/smb/client/dir.c +2 −2
  27. fs/smb/client/inode.c +284 −214
  28. fs/smb/client/misc.c +1 −1
  29. fs/smb/client/namespace.c +62 −51
  30. fs/smb/client/readdir.c +7 −16
  31. fs/smb/client/sess.c +43 −29
  32. fs/smb/client/smb1ops.c +16 −10
  33. fs/smb/client/smb2inode.c +115 −88
  34. fs/smb/client/smb2misc.c +3 −3
  35. fs/smb/client/smb2ops.c +91 −207
  36. fs/smb/client/smb2pdu.c +15 −4
  37. fs/smb/client/smb2proto.h +10 −7
  38. fs/smb/client/smb2transport.c +2 −2
  39. fs/smb/client/transport.c +17 −12
  40. fs/smb/common/smb2pdu.h +22 −0
  41. fs/smb/server/Kconfig +1 −0
  42. fs/smb/server/unicode.c +0 −1
  43. fs/smb/server/unicode.h +4 −321
fs/jfs/Kconfig+1−0
@@ -3,6 +3,7 @@ config JFS_FS · 2 unmodified lines
3 tristate "JFS filesystem support"3 tristate "JFS filesystem support"
4 select BUFFER_HEAD4 select BUFFER_HEAD
5 select NLS5 select NLS
6 select NLS_UCS2_UTILS
6 select CRC327 select CRC32
7 select LEGACY_DIRECT_IO8 select LEGACY_DIRECT_IO
8 help9 help
fs/jfs/Makefile+1−1
@@ -9,7 +9,7 @@ jfs-y := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \ · 8 unmodified lines
9 jfs_xtree.o jfs_imap.o jfs_debug.o jfs_dmap.o \9 jfs_xtree.o jfs_imap.o jfs_debug.o jfs_dmap.o \
10 jfs_unicode.o jfs_dtree.o jfs_inode.o jfs_discard.o \10 jfs_unicode.o jfs_dtree.o jfs_inode.o jfs_discard.o \
11 jfs_extent.o symlink.o jfs_metapage.o \11 jfs_extent.o symlink.o jfs_metapage.o \
12 jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o \12 jfs_logmgr.o jfs_txnmgr.o \
13 resize.o xattr.o ioctl.o13 resize.o xattr.o ioctl.o
14 14
15jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o15jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o
fs/jfs/jfs_unicode.h+5−12
@@ -8,16 +8,9 @@ · 7 unmodified lines
8 8
9#include <linux/slab.h>9#include <linux/slab.h>
10#include <asm/byteorder.h>10#include <asm/byteorder.h>
11#include "../nls/nls_ucs2_data.h"
11#include "jfs_types.h"12#include "jfs_types.h"
12 13
13typedef struct {
14 wchar_t start;
15 wchar_t end;
16 signed char *table;
17} UNICASERANGE;
18
19extern signed char UniUpperTable[512];
20extern UNICASERANGE UniUpperRange[];
21extern int get_UCSname(struct component_name *, struct dentry *);14extern int get_UCSname(struct component_name *, struct dentry *);
22extern int jfs_strfromUCS_le(char *, const __le16 *, int, struct nls_table *);15extern int jfs_strfromUCS_le(char *, const __le16 *, int, struct nls_table *);
23 16
@@ -107,12 +100,12 @@ static inline wchar_t *UniStrncpy_from_le(wchar_t * ucs1, const __le16 * ucs2, · 83 unmodified lines
107 */100 */
108static inline wchar_t UniToupper(wchar_t uc)101static inline wchar_t UniToupper(wchar_t uc)
109{102{
110 UNICASERANGE *rp;103 const struct UniCaseRange *rp;
111 104
112 if (uc < sizeof(UniUpperTable)) { /* Latin characters */105 if (uc < sizeof(NlsUniUpperTable)) { /* Latin characters */
113 return uc + UniUpperTable[uc]; /* Use base tables */106 return uc + NlsUniUpperTable[uc]; /* Use base tables */
114 } else {107 } else {
115 rp = UniUpperRange; /* Use range tables */108 rp = NlsUniUpperRange; /* Use range tables */
116 while (rp->start) {109 while (rp->start) {
117 if (uc < rp->start) /* Before start of range */110 if (uc < rp->start) /* Before start of range */
118 return uc; /* Uppercase = input */111 return uc; /* Uppercase = input */
fs/jfs/jfs_uniupr.c+0−121
@@ -1,121 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) International Business Machines Corp., 2000-2002
4 */
5
6#include <linux/fs.h>
7#include "jfs_unicode.h"
8
9/*
10 * Latin upper case
11 */
12signed char UniUpperTable[512] = {
13 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
14 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
17 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
19 0,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32, /* 060-06f */
20 -32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32, 0, 0, 0, 0, 0, /* 070-07f */
21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
24 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
27 -32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32, /* 0e0-0ef */
28 -32,-32,-32,-32,-32,-32,-32, 0,-32,-32,-32,-32,-32,-32,-32,121, /* 0f0-0ff */
29 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
30 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
31 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
32 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
33 -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
34 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
35 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
36 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
37 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
38 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
39 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
40 -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
41 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
42 -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,-79, 0, -1, /* 1d0-1df */
43 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
44 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
45};
46
47/* Upper case range - Greek */
48static signed char UniCaseRangeU03a0[47] = {
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-38,-37,-37,-37, /* 3a0-3af */
50 0,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32, /* 3b0-3bf */
51 -32,-32,-31,-32,-32,-32,-32,-32,-32,-32,-32,-32,-64,-63,-63,
52};
53
54/* Upper case range - Cyrillic */
55static signed char UniCaseRangeU0430[48] = {
56 -32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32, /* 430-43f */
57 -32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32, /* 440-44f */
58 0,-80,-80,-80,-80,-80,-80,-80,-80,-80,-80,-80,-80, 0,-80,-80, /* 450-45f */
59};
60
61/* Upper case range - Extended cyrillic */
62static signed char UniCaseRangeU0490[61] = {
63 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
64 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
65 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
66 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
67};
68
69/* Upper case range - Extended latin and greek */
70static signed char UniCaseRangeU1e00[509] = {
71 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
72 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
73 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
74 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
75 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
76 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
77 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
78 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
79 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
80 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0,-59, 0, -1, 0, -1, /* 1e90-1e9f */
81 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
82 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
83 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
84 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
85 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
86 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
87 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
88 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
89 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
90 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
91 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
92 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
93 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
94 74, 74, 86, 86, 86, 86,100,100, 0, 0,112,112,126,126, 0, 0, /* 1f70-1f7f */
95 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
96 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
97 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
98 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
99 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
100 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
101 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
102 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103};
104
105/* Upper case range - Wide latin */
106static signed char UniCaseRangeUff40[27] = {
107 0,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32, /* ff40-ff4f */
108 -32,-32,-32,-32,-32,-32,-32,-32,-32,-32,-32,
109};
110
111/*
112 * Upper Case Range
113 */
114UNICASERANGE UniUpperRange[] = {
115 { 0x03a0, 0x03ce, UniCaseRangeU03a0 },
116 { 0x0430, 0x045f, UniCaseRangeU0430 },
117 { 0x0490, 0x04cc, UniCaseRangeU0490 },
118 { 0x1e00, 0x1ffc, UniCaseRangeU1e00 },
119 { 0xff40, 0xff5a, UniCaseRangeUff40 },
120 { 0 }
121};
fs/nls/Kconfig+8−0
@@ -617,4 +617,12 @@ config NLS_UTF8 · 616 unmodified lines
617 input/output character sets. Say Y here for the UTF-8 encoding of617 input/output character sets. Say Y here for the UTF-8 encoding of
618 the Unicode/ISO9646 universal character set.618 the Unicode/ISO9646 universal character set.
619 619
620config NLS_UCS2_UTILS
621 tristate "NLS UCS-2 UTILS"
622 help
623 Set of older UCS-2 conversion utilities and tables used by some
624 filesystems including SMB/CIFS. This includes upper case conversion
625 tables. This will automatically be selected when the filesystem
626 that uses it is selected.
627
620endif # NLS628endif # NLS
fs/nls/Makefile+1−0
@@ -54,3 +54,4 @@ obj-$(CONFIG_NLS_MAC_INUIT) += mac-inuit.o · 53 unmodified lines
54obj-$(CONFIG_NLS_MAC_ROMANIAN) += mac-romanian.o54obj-$(CONFIG_NLS_MAC_ROMANIAN) += mac-romanian.o
55obj-$(CONFIG_NLS_MAC_ROMAN) += mac-roman.o55obj-$(CONFIG_NLS_MAC_ROMAN) += mac-roman.o
56obj-$(CONFIG_NLS_MAC_TURKISH) += mac-turkish.o56obj-$(CONFIG_NLS_MAC_TURKISH) += mac-turkish.o
57obj-$(CONFIG_NLS_UCS2_UTILS) += nls_ucs2_utils.o
fs/nls/nls_ucs2_data.h+15−0
@@ -0,0 +1,15 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#ifndef _NLS_UCS2_DATA_H
4#define _NLS_UCS2_DATA_H
5
6struct UniCaseRange {
7 wchar_t start;
8 wchar_t end;
9 signed char *table;
10};
11
12extern signed char NlsUniUpperTable[512];
13extern const struct UniCaseRange NlsUniUpperRange[];
14
15#endif /* _NLS_UCS2_DATA_H */
fs/nls/nls_ucs2_utils.crenamed from fs/smb/server/uniupr.h+17−139
@@ -1,19 +1,27 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */1// SPDX-License-Identifier: GPL-2.0-or-later
2/*2/*
3 * Some of the source code in this file came from fs/cifs/uniupr.h3 * Some of the source code in this file came from fs/cifs/uniupr.h
4 * Copyright (c) International Business Machines Corp., 2000,20024 * Copyright (c) International Business Machines Corp., 2000,2002
5 *5 *
6 * uniupr.h - Unicode compressed case ranges6 * Some of the source code in this file came from fs/cifs/cifs_unicode.c
7 *
8 * Copyright (c) International Business Machines Corp., 2000,2009
9 * Modified by Steve French (sfrench@us.ibm.com)
10 * Modified by Namjae Jeon (linkinjeon@kernel.org)
7 *11 *
8 */12 */
9#ifndef __KSMBD_UNIUPR_H13#include <linux/fs.h>
10#define __KSMBD_UNIUPR_H14#include <linux/module.h>
15#include <linux/slab.h>
16#include <asm/unaligned.h>
17#include "nls_ucs2_utils.h"
18
19MODULE_LICENSE("GPL");
11 20
12#ifndef UNIUPR_NOUPPER
13/*21/*
14 * Latin upper case22 * Latin upper case
15 */23 */
16signed char SmbUniUpperTable[512] = {24signed char NlsUniUpperTable[512] = {
17 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
@@ -51,6 +59,7 @@ signed char SmbUniUpperTable[512] = { · 31 unmodified lines
51 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */59 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
52 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */60 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
53};61};
62EXPORT_SYMBOL_GPL(NlsUniUpperTable);
54 63
55/* Upper case range - Greek */64/* Upper case range - Greek */
56static signed char UniCaseRangeU03a0[47] = {65static signed char UniCaseRangeU03a0[47] = {
@@ -126,7 +135,7 @@ static signed char UniCaseRangeUff40[27] = { · 69 unmodified lines
126/*135/*
127 * Upper Case Range136 * Upper Case Range
128 */137 */
129const struct UniCaseRange SmbUniUpperRange[] = {138const struct UniCaseRange NlsUniUpperRange[] = {
130 {0x03a0, 0x03ce, UniCaseRangeU03a0},139 {0x03a0, 0x03ce, UniCaseRangeU03a0},
131 {0x0430, 0x045f, UniCaseRangeU0430},140 {0x0430, 0x045f, UniCaseRangeU0430},
132 {0x0490, 0x04cc, UniCaseRangeU0490},141 {0x0490, 0x04cc, UniCaseRangeU0490},
@@ -134,135 +143,4 @@ const struct UniCaseRange SmbUniUpperRange[] = { · 1 unmodified line
134 {0xff40, 0xff5a, UniCaseRangeUff40},143 {0xff40, 0xff5a, UniCaseRangeUff40},
135 {0}144 {0}
136};145};
137#endif146EXPORT_SYMBOL_GPL(NlsUniUpperRange);
138
139#ifndef UNIUPR_NOLOWER
140/*
141 * Latin lower case
142 */
143signed char CifsUniLowerTable[512] = {
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
148 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
149 32, 32, 32, /* 040-04f */
150 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0,
151 0, 0, 0, /* 050-05f */
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
158 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
159 32, 32, 32, 32, /* 0c0-0cf */
160 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32,
161 32, 32, 32, 0, /* 0d0-0df */
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
164 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
165 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
166 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
167 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
168 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
169 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
170 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
171 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0,
172 0, /* 170-17f */
173 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79,
174 0, /* 180-18f */
175 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
176 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
177 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
178 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
179 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
180 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
181 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
182};
183
184/* Lower case range - Greek */
185static signed char UniCaseRangeL0380[44] = {
186 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
187 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
188 32, 32, 32, /* 390-39f */
189 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
190};
191
192/* Lower case range - Cyrillic */
193static signed char UniCaseRangeL0400[48] = {
194 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
195 0, 80, 80, /* 400-40f */
196 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
197 32, 32, 32, /* 410-41f */
198 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
199 32, 32, 32, /* 420-42f */
200};
201
202/* Lower case range - Extended cyrillic */
203static signed char UniCaseRangeL0490[60] = {
204 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
205 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
206 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
207 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
208};
209
210/* Lower case range - Extended latin and greek */
211static signed char UniCaseRangeL1e00[504] = {
212 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
213 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
214 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
215 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
216 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
217 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
218 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
219 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
220 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
221 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
222 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
223 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
224 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
225 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
226 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
227 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
228 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
229 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
230 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
231 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
232 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
233 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
234 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
235 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
236 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
237 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
238 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
239 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
240 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0,
241 0, 0, /* 1fc0-1fcf */
242 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
243 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0,
244 0, 0, /* 1fe0-1fef */
245 0, 0, 0, 0, 0, 0, 0, 0,
246};
247
248/* Lower case range - Wide latin */
249static signed char UniCaseRangeLff20[27] = {
250 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
251 32, /* ff20-ff2f */
252 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
253};
254
255/*
256 * Lower Case Range
257 */
258const struct UniCaseRange CifsUniLowerRange[] = {
259 {0x0380, 0x03ab, UniCaseRangeL0380},
260 {0x0400, 0x042f, UniCaseRangeL0400},
261 {0x0490, 0x04cb, UniCaseRangeL0490},
262 {0x1e00, 0x1ff7, UniCaseRangeL1e00},
263 {0xff20, 0xff3a, UniCaseRangeLff20},
264 {0}
265};
266#endif
267
268#endif /* __KSMBD_UNIUPR_H */
fs/nls/nls_ucs2_utils.h+285−0
@@ -0,0 +1,285 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Some of the source code in this file came from fs/cifs/cifs_unicode.c
4 * and then via server/unicode.c
5 * cifs_unicode: Unicode kernel case support
6 *
7 * Function:
8 * Convert a unicode character to upper or lower case using
9 * compressed tables.
10 *
11 * Copyright (c) International Business Machines Corp., 2000,2009
12 *
13 *
14 * Notes:
15 * These APIs are based on the C library functions. The semantics
16 * should match the C functions but with expanded size operands.
17 *
18 * The upper/lower functions are based on a table created by mkupr.
19 * This is a compressed table of upper and lower case conversion.
20 *
21 */
22#ifndef _NLS_UCS2_UTILS_H
23#define _NLS_UCS2_UTILS_H
24
25#include <asm/byteorder.h>
26#include <linux/types.h>
27#include <linux/nls.h>
28#include <linux/unicode.h>
29#include "nls_ucs2_data.h"
30
31/*
32 * Windows maps these to the user defined 16 bit Unicode range since they are
33 * reserved symbols (along with \ and /), otherwise illegal to store
34 * in filenames in NTFS
35 */
36#define UNI_ASTERISK ((__u16)('*' + 0xF000))
37#define UNI_QUESTION ((__u16)('?' + 0xF000))
38#define UNI_COLON ((__u16)(':' + 0xF000))
39#define UNI_GRTRTHAN ((__u16)('>' + 0xF000))
40#define UNI_LESSTHAN ((__u16)('<' + 0xF000))
41#define UNI_PIPE ((__u16)('|' + 0xF000))
42#define UNI_SLASH ((__u16)('\\' + 0xF000))
43
44/*
45 * UniStrcat: Concatenate the second string to the first
46 *
47 * Returns:
48 * Address of the first string
49 */
50static inline wchar_t *UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
51{
52 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
53
54 while (*ucs1++)
55 /*NULL*/; /* To end of first string */
56 ucs1--; /* Return to the null */
57 while ((*ucs1++ = *ucs2++))
58 /*NULL*/; /* copy string 2 over */
59 return anchor;
60}
61
62/*
63 * UniStrchr: Find a character in a string
64 *
65 * Returns:
66 * Address of first occurrence of character in string
67 * or NULL if the character is not in the string
68 */
69static inline wchar_t *UniStrchr(const wchar_t *ucs, wchar_t uc)
70{
71 while ((*ucs != uc) && *ucs)
72 ucs++;
73
74 if (*ucs == uc)
75 return (wchar_t *)ucs;
76 return NULL;
77}
78
79/*
80 * UniStrcmp: Compare two strings
81 *
82 * Returns:
83 * < 0: First string is less than second
84 * = 0: Strings are equal
85 * > 0: First string is greater than second
86 */
87static inline int UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
88{
89 while ((*ucs1 == *ucs2) && *ucs1) {
90 ucs1++;
91 ucs2++;
92 }
93 return (int)*ucs1 - (int)*ucs2;
94}
95
96/*
97 * UniStrcpy: Copy a string
98 */
99static inline wchar_t *UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
100{
101 wchar_t *anchor = ucs1; /* save the start of result string */
102
103 while ((*ucs1++ = *ucs2++))
104 /*NULL*/;
105 return anchor;
106}
107
108/*
109 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
110 */
111static inline size_t UniStrlen(const wchar_t *ucs1)
112{
113 int i = 0;
114
115 while (*ucs1++)
116 i++;
117 return i;
118}
119
120/*
121 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
122 * string (length limited)
123 */
124static inline size_t UniStrnlen(const wchar_t *ucs1, int maxlen)
125{
126 int i = 0;
127
128 while (*ucs1++) {
129 i++;
130 if (i >= maxlen)
131 break;
132 }
133 return i;
134}
135
136/*
137 * UniStrncat: Concatenate length limited string
138 */
139static inline wchar_t *UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
140{
141 wchar_t *anchor = ucs1; /* save pointer to string 1 */
142
143 while (*ucs1++)
144 /*NULL*/;
145 ucs1--; /* point to null terminator of s1 */
146 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
147 ucs1++;
148 ucs2++;
149 }
150 *ucs1 = 0; /* Null terminate the result */
151 return anchor;
152}
153
154/*
155 * UniStrncmp: Compare length limited string
156 */
157static inline int UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
158{
159 if (!n)
160 return 0; /* Null strings are equal */
161 while ((*ucs1 == *ucs2) && *ucs1 && --n) {
162 ucs1++;
163 ucs2++;
164 }
165 return (int)*ucs1 - (int)*ucs2;
166}
167
168/*
169 * UniStrncmp_le: Compare length limited string - native to little-endian
170 */
171static inline int
172UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
173{
174 if (!n)
175 return 0; /* Null strings are equal */
176 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
177 ucs1++;
178 ucs2++;
179 }
180 return (int)*ucs1 - (int)__le16_to_cpu(*ucs2);
181}
182
183/*
184 * UniStrncpy: Copy length limited string with pad
185 */
186static inline wchar_t *UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
187{
188 wchar_t *anchor = ucs1;
189
190 while (n-- && *ucs2) /* Copy the strings */
191 *ucs1++ = *ucs2++;
192
193 n++;
194 while (n--) /* Pad with nulls */
195 *ucs1++ = 0;
196 return anchor;
197}
198
199/*
200 * UniStrncpy_le: Copy length limited string with pad to little-endian
201 */
202static inline wchar_t *UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
203{
204 wchar_t *anchor = ucs1;
205
206 while (n-- && *ucs2) /* Copy the strings */
207 *ucs1++ = __le16_to_cpu(*ucs2++);
208
209 n++;
210 while (n--) /* Pad with nulls */
211 *ucs1++ = 0;
212 return anchor;
213}
214
215/*
216 * UniStrstr: Find a string in a string
217 *
218 * Returns:
219 * Address of first match found
220 * NULL if no matching string is found
221 */
222static inline wchar_t *UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
223{
224 const wchar_t *anchor1 = ucs1;
225 const wchar_t *anchor2 = ucs2;
226
227 while (*ucs1) {
228 if (*ucs1 == *ucs2) {
229 /* Partial match found */
230 ucs1++;
231 ucs2++;
232 } else {
233 if (!*ucs2) /* Match found */
234 return (wchar_t *)anchor1;
235 ucs1 = ++anchor1; /* No match */
236 ucs2 = anchor2;
237 }
238 }
239
240 if (!*ucs2) /* Both end together */
241 return (wchar_t *)anchor1; /* Match found */
242 return NULL; /* No match */
243}
244
245#ifndef UNIUPR_NOUPPER
246/*
247 * UniToupper: Convert a unicode character to upper case
248 */
249static inline wchar_t UniToupper(register wchar_t uc)
250{
251 register const struct UniCaseRange *rp;
252
253 if (uc < sizeof(NlsUniUpperTable)) {
254 /* Latin characters */
255 return uc + NlsUniUpperTable[uc]; /* Use base tables */
256 }
257
258 rp = NlsUniUpperRange; /* Use range tables */
259 while (rp->start) {
260 if (uc < rp->start) /* Before start of range */
261 return uc; /* Uppercase = input */
262 if (uc <= rp->end) /* In range */
263 return uc + rp->table[uc - rp->start];
264 rp++; /* Try next range */
265 }
266 return uc; /* Past last range */
267}
268
269/*
270 * UniStrupr: Upper case a unicode string
271 */
272static inline __le16 *UniStrupr(register __le16 *upin)
273{
274 register __le16 *up;
275
276 up = upin;
277 while (*up) { /* For all characters */
278 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
279 up++;
280 }
281 return upin; /* Return input pointer */
282}
283#endif /* UNIUPR_NOUPPER */
284
285#endif /* _NLS_UCS2_UTILS_H */
fs/smb/client/Kconfig+1−0
@@ -3,6 +3,7 @@ config CIFS · 2 unmodified lines
3 tristate "SMB3 and CIFS support (advanced network filesystem)"3 tristate "SMB3 and CIFS support (advanced network filesystem)"
4 depends on INET4 depends on INET
5 select NLS5 select NLS
6 select NLS_UCS2_UTILS
6 select CRYPTO7 select CRYPTO
7 select CRYPTO_MD58 select CRYPTO_MD5
8 select CRYPTO_SHA2569 select CRYPTO_SHA256
fs/smb/client/Makefile+3−2
@@ -11,7 +11,8 @@ cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \ · 10 unmodified lines
11 readdir.o ioctl.o sess.o export.o unc.o winucase.o \11 readdir.o ioctl.o sess.o export.o unc.o winucase.o \
12 smb2ops.o smb2maperror.o smb2transport.o \12 smb2ops.o smb2maperror.o smb2transport.o \
13 smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \13 smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \
14 dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o14 dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o \
15 namespace.o
15 16
16$(obj)/asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.h17$(obj)/asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.h
17 18
@@ -21,7 +22,7 @@ cifs-$(CONFIG_CIFS_XATTR) += xattr.o · 3 unmodified lines
21 22
22cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o23cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
23 24
24cifs-$(CONFIG_CIFS_DFS_UPCALL) += cifs_dfs_ref.o dfs_cache.o dfs.o25cifs-$(CONFIG_CIFS_DFS_UPCALL) += dfs_cache.o dfs.o
25 26
26cifs-$(CONFIG_CIFS_SWN_UPCALL) += netlink.o cifs_swn.o27cifs-$(CONFIG_CIFS_SWN_UPCALL) += netlink.o cifs_swn.o
27 28
fs/smb/client/cached_dir.c+1−1
@@ -218,7 +218,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, · 217 unmodified lines
218 .tcon = tcon,218 .tcon = tcon,
219 .path = path,219 .path = path,
220 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),220 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
221 .desired_access = FILE_READ_ATTRIBUTES,221 .desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES,
222 .disposition = FILE_OPEN,222 .disposition = FILE_OPEN,
223 .fid = pfid,223 .fid = pfid,
224 };224 };
fs/smb/client/cifs_debug.c+1−1
@@ -331,7 +331,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) · 330 unmodified lines
331 spin_lock(&cifs_tcp_ses_lock);331 spin_lock(&cifs_tcp_ses_lock);
332 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {332 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
333 /* channel info will be printed as a part of sessions below */333 /* channel info will be printed as a part of sessions below */
334 if (CIFS_SERVER_IS_CHAN(server))334 if (SERVER_IS_CHAN(server))
335 continue;335 continue;
336 336
337 c++;337 c++;
fs/smb/client/cifs_unicode.c+0−1
@@ -8,7 +8,6 @@ · 7 unmodified lines
8#include <linux/slab.h>8#include <linux/slab.h>
9#include "cifs_fs_sb.h"9#include "cifs_fs_sb.h"
10#include "cifs_unicode.h"10#include "cifs_unicode.h"
11#include "cifs_uniupr.h"
12#include "cifspdu.h"11#include "cifspdu.h"
13#include "cifsglob.h"12#include "cifsglob.h"
14#include "cifs_debug.h"13#include "cifs_debug.h"
fs/smb/client/cifs_unicode.h+1−329
@@ -21,21 +21,7 @@ · 20 unmodified lines
21#include <asm/byteorder.h>21#include <asm/byteorder.h>
22#include <linux/types.h>22#include <linux/types.h>
23#include <linux/nls.h>23#include <linux/nls.h>
24 24#include "../../nls/nls_ucs2_utils.h"
25#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
26
27/*
28 * Windows maps these to the user defined 16 bit Unicode range since they are
29 * reserved symbols (along with \ and /), otherwise illegal to store
30 * in filenames in NTFS
31 */
32#define UNI_ASTERISK (__u16) ('*' + 0xF000)
33#define UNI_QUESTION (__u16) ('?' + 0xF000)
34#define UNI_COLON (__u16) (':' + 0xF000)
35#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
36#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
37#define UNI_PIPE (__u16) ('|' + 0xF000)
38#define UNI_SLASH (__u16) ('\\' + 0xF000)
39 25
40/*26/*
41 * Macs use an older "SFM" mapping of the symbols above. Fortunately it does27 * Macs use an older "SFM" mapping of the symbols above. Fortunately it does
@@ -68,27 +54,6 @@ · 26 unmodified lines
68#define SFM_MAP_UNI_RSVD 154#define SFM_MAP_UNI_RSVD 1
69#define SFU_MAP_UNI_RSVD 255#define SFU_MAP_UNI_RSVD 2
70 56
71/* Just define what we want from uniupr.h. We don't want to define the tables
72 * in each source file.
73 */
74#ifndef UNICASERANGE_DEFINED
75struct UniCaseRange {
76 wchar_t start;
77 wchar_t end;
78 signed char *table;
79};
80#endif /* UNICASERANGE_DEFINED */
81
82#ifndef UNIUPR_NOUPPER
83extern signed char CifsUniUpperTable[512];
84extern const struct UniCaseRange CifsUniUpperRange[];
85#endif /* UNIUPR_NOUPPER */
86
87#ifndef UNIUPR_NOLOWER
88extern signed char CifsUniLowerTable[512];
89extern const struct UniCaseRange CifsUniLowerRange[];
90#endif /* UNIUPR_NOLOWER */
91
92#ifdef __KERNEL__57#ifdef __KERNEL__
93int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,58int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
94 const struct nls_table *cp, int map_type);59 const struct nls_table *cp, int map_type);
@@ -108,297 +73,4 @@ extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen, · 13 unmodified lines
108 73
109wchar_t cifs_toupper(wchar_t in);74wchar_t cifs_toupper(wchar_t in);
110 75
111/*
112 * UniStrcat: Concatenate the second string to the first
113 *
114 * Returns:
115 * Address of the first string
116 */
117static inline __le16 *
118UniStrcat(__le16 *ucs1, const __le16 *ucs2)
119{
120 __le16 *anchor = ucs1; /* save a pointer to start of ucs1 */
121
122 while (*ucs1++) ; /* To end of first string */
123 ucs1--; /* Return to the null */
124 while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
125 return anchor;
126}
127
128/*
129 * UniStrchr: Find a character in a string
130 *
131 * Returns:
132 * Address of first occurrence of character in string
133 * or NULL if the character is not in the string
134 */
135static inline wchar_t *
136UniStrchr(const wchar_t *ucs, wchar_t uc)
137{
138 while ((*ucs != uc) && *ucs)
139 ucs++;
140
141 if (*ucs == uc)
142 return (wchar_t *) ucs;
143 return NULL;
144}
145
146/*
147 * UniStrcmp: Compare two strings
148 *
149 * Returns:
150 * < 0: First string is less than second
151 * = 0: Strings are equal
152 * > 0: First string is greater than second
153 */
154static inline int
155UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
156{
157 while ((*ucs1 == *ucs2) && *ucs1) {
158 ucs1++;
159 ucs2++;
160 }
161 return (int) *ucs1 - (int) *ucs2;
162}
163
164/*
165 * UniStrcpy: Copy a string
166 */
167static inline wchar_t *
168UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
169{
170 wchar_t *anchor = ucs1; /* save the start of result string */
171
172 while ((*ucs1++ = *ucs2++)) ;
173 return anchor;
174}
175
176/*
177 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
178 */
179static inline size_t
180UniStrlen(const wchar_t *ucs1)
181{
182 int i = 0;
183
184 while (*ucs1++)
185 i++;
186 return i;
187}
188
189/*
190 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
191 * string (length limited)
192 */
193static inline size_t
194UniStrnlen(const wchar_t *ucs1, int maxlen)
195{
196 int i = 0;
197
198 while (*ucs1++) {
199 i++;
200 if (i >= maxlen)
201 break;
202 }
203 return i;
204}
205
206/*
207 * UniStrncat: Concatenate length limited string
208 */
209static inline wchar_t *
210UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
211{
212 wchar_t *anchor = ucs1; /* save pointer to string 1 */
213
214 while (*ucs1++) ;
215 ucs1--; /* point to null terminator of s1 */
216 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
217 ucs1++;
218 ucs2++;
219 }
220 *ucs1 = 0; /* Null terminate the result */
221 return (anchor);
222}
223
224/*
225 * UniStrncmp: Compare length limited string
226 */
227static inline int
228UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
229{
230 if (!n)
231 return 0; /* Null strings are equal */
232 while ((*ucs1 == *ucs2) && *ucs1 && --n) {
233 ucs1++;
234 ucs2++;
235 }
236 return (int) *ucs1 - (int) *ucs2;
237}
238
239/*
240 * UniStrncmp_le: Compare length limited string - native to little-endian
241 */
242static inline int
243UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
244{
245 if (!n)
246 return 0; /* Null strings are equal */
247 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
248 ucs1++;
249 ucs2++;
250 }
251 return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
252}
253
254/*
255 * UniStrncpy: Copy length limited string with pad
256 */
257static inline wchar_t *
258UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
259{
260 wchar_t *anchor = ucs1;
261
262 while (n-- && *ucs2) /* Copy the strings */
263 *ucs1++ = *ucs2++;
264
265 n++;
266 while (n--) /* Pad with nulls */
267 *ucs1++ = 0;
268 return anchor;
269}
270
271/*
272 * UniStrncpy_le: Copy length limited string with pad to little-endian
273 */
274static inline wchar_t *
275UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
276{
277 wchar_t *anchor = ucs1;
278
279 while (n-- && *ucs2) /* Copy the strings */
280 *ucs1++ = __le16_to_cpu(*ucs2++);
281
282 n++;
283 while (n--) /* Pad with nulls */
284 *ucs1++ = 0;
285 return anchor;
286}
287
288/*
289 * UniStrstr: Find a string in a string
290 *
291 * Returns:
292 * Address of first match found
293 * NULL if no matching string is found
294 */
295static inline wchar_t *
296UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
297{
298 const wchar_t *anchor1 = ucs1;
299 const wchar_t *anchor2 = ucs2;
300
301 while (*ucs1) {
302 if (*ucs1 == *ucs2) {
303 /* Partial match found */
304 ucs1++;
305 ucs2++;
306 } else {
307 if (!*ucs2) /* Match found */
308 return (wchar_t *) anchor1;
309 ucs1 = ++anchor1; /* No match */
310 ucs2 = anchor2;
311 }
312 }
313
314 if (!*ucs2) /* Both end together */
315 return (wchar_t *) anchor1; /* Match found */
316 return NULL; /* No match */
317}
318
319#ifndef UNIUPR_NOUPPER
320/*
321 * UniToupper: Convert a unicode character to upper case
322 */
323static inline wchar_t
324UniToupper(register wchar_t uc)
325{
326 register const struct UniCaseRange *rp;
327
328 if (uc < sizeof(CifsUniUpperTable)) {
329 /* Latin characters */
330 return uc + CifsUniUpperTable[uc]; /* Use base tables */
331 } else {
332 rp = CifsUniUpperRange; /* Use range tables */
333 while (rp->start) {
334 if (uc < rp->start) /* Before start of range */
335 return uc; /* Uppercase = input */
336 if (uc <= rp->end) /* In range */
337 return uc + rp->table[uc - rp->start];
338 rp++; /* Try next range */
339 }
340 }
341 return uc; /* Past last range */
342}
343
344/*
345 * UniStrupr: Upper case a unicode string
346 */
347static inline __le16 *
348UniStrupr(register __le16 *upin)
349{
350 register __le16 *up;
351
352 up = upin;
353 while (*up) { /* For all characters */
354 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
355 up++;
356 }
357 return upin; /* Return input pointer */
358}
359#endif /* UNIUPR_NOUPPER */
360
361#ifndef UNIUPR_NOLOWER
362/*
363 * UniTolower: Convert a unicode character to lower case
364 */
365static inline wchar_t
366UniTolower(register wchar_t uc)
367{
368 register const struct UniCaseRange *rp;
369
370 if (uc < sizeof(CifsUniLowerTable)) {
371 /* Latin characters */
372 return uc + CifsUniLowerTable[uc]; /* Use base tables */
373 } else {
374 rp = CifsUniLowerRange; /* Use range tables */
375 while (rp->start) {
376 if (uc < rp->start) /* Before start of range */
377 return uc; /* Uppercase = input */
378 if (uc <= rp->end) /* In range */
379 return uc + rp->table[uc - rp->start];
380 rp++; /* Try next range */
381 }
382 }
383 return uc; /* Past last range */
384}
385
386/*
387 * UniStrlwr: Lower case a unicode string
388 */
389static inline wchar_t *
390UniStrlwr(register wchar_t *upin)
391{
392 register wchar_t *up;
393
394 up = upin;
395 while (*up) { /* For all characters */
396 *up = UniTolower(*up);
397 up++;
398 }
399 return upin; /* Return input pointer */
400}
401
402#endif
403
404#endif /* _CIFS_UNICODE_H */76#endif /* _CIFS_UNICODE_H */
fs/smb/client/cifs_uniupr.h+0−239
@@ -1,239 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright (c) International Business Machines Corp., 2000,2002
4 *
5 * uniupr.h - Unicode compressed case ranges
6*/
7
8#ifndef UNIUPR_NOUPPER
9/*
10 * Latin upper case
11 */
12signed char CifsUniUpperTable[512] = {
13 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
14 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
17 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
19 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
20 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
24 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
27 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
28 -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
29 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
30 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
31 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
32 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
33 -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
34 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
35 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
36 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
37 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
38 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
39 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
40 -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
41 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
42 -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
43 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
44 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
45};
46
47/* Upper case range - Greek */
48static signed char UniCaseRangeU03a0[47] = {
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
50 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
51 -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
52 -63, -63,
53};
54
55/* Upper case range - Cyrillic */
56static signed char UniCaseRangeU0430[48] = {
57 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
58 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
59 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
60};
61
62/* Upper case range - Extended cyrillic */
63static signed char UniCaseRangeU0490[61] = {
64 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
65 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
66 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
67 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
68};
69
70/* Upper case range - Extended latin and greek */
71static signed char UniCaseRangeU1e00[509] = {
72 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
73 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
74 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
75 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
76 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
77 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
78 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
79 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
80 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
81 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
82 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
83 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
84 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
85 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
86 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
87 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
88 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
89 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
90 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
91 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
92 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
93 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
94 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
95 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
96 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
97 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
98 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
99 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
100 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
101 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
102 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
103 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104};
105
106/* Upper case range - Wide latin */
107static signed char UniCaseRangeUff40[27] = {
108 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
109 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
110};
111
112/*
113 * Upper Case Range
114 */
115const struct UniCaseRange CifsUniUpperRange[] = {
116 {0x03a0, 0x03ce, UniCaseRangeU03a0},
117 {0x0430, 0x045f, UniCaseRangeU0430},
118 {0x0490, 0x04cc, UniCaseRangeU0490},
119 {0x1e00, 0x1ffc, UniCaseRangeU1e00},
120 {0xff40, 0xff5a, UniCaseRangeUff40},
121 {0}
122};
123#endif
124
125#ifndef UNIUPR_NOLOWER
126/*
127 * Latin lower case
128 */
129signed char CifsUniLowerTable[512] = {
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
134 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
135 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
142 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
143 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
146 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
147 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
148 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
149 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
150 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
151 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
152 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
153 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
154 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
155 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
156 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
157 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
158 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
159 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
160 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
161 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
162};
163
164/* Lower case range - Greek */
165static signed char UniCaseRangeL0380[44] = {
166 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
167 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
168 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
169};
170
171/* Lower case range - Cyrillic */
172static signed char UniCaseRangeL0400[48] = {
173 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
174 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
175 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
176};
177
178/* Lower case range - Extended cyrillic */
179static signed char UniCaseRangeL0490[60] = {
180 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
181 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
182 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
183 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
184};
185
186/* Lower case range - Extended latin and greek */
187static signed char UniCaseRangeL1e00[504] = {
188 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
189 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
190 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
191 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
192 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
193 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
194 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
195 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
196 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
197 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
198 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
199 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
200 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
201 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
202 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
203 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
204 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
205 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
206 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
207 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
208 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
209 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
210 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
211 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
212 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
213 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
214 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
215 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
216 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
217 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
218 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
219 0, 0, 0, 0, 0, 0, 0, 0,
220};
221
222/* Lower case range - Wide latin */
223static signed char UniCaseRangeLff20[27] = {
224 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
225 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
226};
227
228/*
229 * Lower Case Range
230 */
231const struct UniCaseRange CifsUniLowerRange[] = {
232 {0x0380, 0x03ab, UniCaseRangeL0380},
233 {0x0400, 0x042f, UniCaseRangeL0400},
234 {0x0490, 0x04cb, UniCaseRangeL0490},
235 {0x1e00, 0x1ff7, UniCaseRangeL1e00},
236 {0xff20, 0xff3a, UniCaseRangeLff20},
237 {0}
238};
239#endif
fs/smb/client/cifsfs.c+1−1
@@ -1805,7 +1805,7 @@ exit_cifs(void) · 1804 unmodified lines
1805 cifs_dbg(NOISY, "exit_smb3\n");1805 cifs_dbg(NOISY, "exit_smb3\n");
1806 unregister_filesystem(&cifs_fs_type);1806 unregister_filesystem(&cifs_fs_type);
1807 unregister_filesystem(&smb3_fs_type);1807 unregister_filesystem(&smb3_fs_type);
1808 cifs_dfs_release_automount_timer();1808 cifs_release_automount_timer();
1809 exit_cifs_idmap();1809 exit_cifs_idmap();
1810#ifdef CONFIG_CIFS_SWN_UPCALL1810#ifdef CONFIG_CIFS_SWN_UPCALL
1811 cifs_genl_exit();1811 cifs_genl_exit();
fs/smb/client/cifsfs.h+2−9
@@ -81,7 +81,7 @@ extern int cifs_fiemap(struct inode *, struct fiemap_extent_info *, u64 start, · 80 unmodified lines
81 81
82extern const struct inode_operations cifs_file_inode_ops;82extern const struct inode_operations cifs_file_inode_ops;
83extern const struct inode_operations cifs_symlink_inode_ops;83extern const struct inode_operations cifs_symlink_inode_ops;
84extern const struct inode_operations cifs_dfs_referral_inode_operations;84extern const struct inode_operations cifs_namespace_inode_operations;
85 85
86 86
87/* Functions related to files and directories */87/* Functions related to files and directories */
@@ -118,14 +118,7 @@ extern void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned · 30 unmodified lines
118extern const struct dentry_operations cifs_dentry_ops;118extern const struct dentry_operations cifs_dentry_ops;
119extern const struct dentry_operations cifs_ci_dentry_ops;119extern const struct dentry_operations cifs_ci_dentry_ops;
120 120
121#ifdef CONFIG_CIFS_DFS_UPCALL121extern struct vfsmount *cifs_d_automount(struct path *path);
122extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
123#else
124static inline struct vfsmount *cifs_dfs_d_automount(struct path *path)
125{
126 return ERR_PTR(-EREMOTE);
127}
128#endif
129 122
130/* Functions related to symlinks */123/* Functions related to symlinks */
131extern const char *cifs_get_link(struct dentry *, struct inode *,124extern const char *cifs_get_link(struct dentry *, struct inode *,
fs/smb/client/cifsglob.h+58−14
@@ -186,6 +186,12 @@ struct cifs_cred { · 185 unmodified lines
186};186};
187 187
188struct cifs_open_info_data {188struct cifs_open_info_data {
189 bool adjust_tz;
190 union {
191 bool reparse_point;
192 bool symlink;
193 };
194 __u32 reparse_tag;
189 char *symlink_target;195 char *symlink_target;
190 union {196 union {
191 struct smb2_file_all_info fi;197 struct smb2_file_all_info fi;
@@ -193,6 +199,10 @@ struct cifs_open_info_data { · 1 unmodified line
193 };199 };
194};200};
195 201
202#define cifs_open_data_reparse(d) \
203 ((d)->reparse_point || \
204 (le32_to_cpu((d)->fi.Attributes) & ATTR_REPARSE))
205
196static inline void cifs_free_open_info(struct cifs_open_info_data *data)206static inline void cifs_free_open_info(struct cifs_open_info_data *data)
197{207{
198 kfree(data->symlink_target);208 kfree(data->symlink_target);
@@ -318,16 +328,21 @@ struct smb_version_operations { · 119 unmodified lines
318 int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,328 int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
319 struct cifs_sb_info *, const char *);329 struct cifs_sb_info *, const char *);
320 /* query path data from the server */330 /* query path data from the server */
321 int (*query_path_info)(const unsigned int xid, struct cifs_tcon *tcon,331 int (*query_path_info)(const unsigned int xid,
322 struct cifs_sb_info *cifs_sb, const char *full_path,332 struct cifs_tcon *tcon,
323 struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);333 struct cifs_sb_info *cifs_sb,
334 const char *full_path,
335 struct cifs_open_info_data *data);
324 /* query file data from the server */336 /* query file data from the server */
325 int (*query_file_info)(const unsigned int xid, struct cifs_tcon *tcon,337 int (*query_file_info)(const unsigned int xid, struct cifs_tcon *tcon,
326 struct cifsFileInfo *cfile, struct cifs_open_info_data *data);338 struct cifsFileInfo *cfile, struct cifs_open_info_data *data);
327 /* query reparse tag from srv to determine which type of special file */339 /* query reparse point to determine which type of special file */
328 int (*query_reparse_tag)(const unsigned int xid, struct cifs_tcon *tcon,340 int (*query_reparse_point)(const unsigned int xid,
329 struct cifs_sb_info *cifs_sb, const char *path,341 struct cifs_tcon *tcon,
330 __u32 *reparse_tag);342 struct cifs_sb_info *cifs_sb,
343 const char *full_path,
344 u32 *tag, struct kvec *rsp,
345 int *rsp_buftype);
331 /* get server index number */346 /* get server index number */
332 int (*get_srv_inum)(const unsigned int xid, struct cifs_tcon *tcon,347 int (*get_srv_inum)(const unsigned int xid, struct cifs_tcon *tcon,
333 struct cifs_sb_info *cifs_sb, const char *full_path, u64 *uniqueid,348 struct cifs_sb_info *cifs_sb, const char *full_path, u64 *uniqueid,
@@ -376,9 +391,12 @@ struct smb_version_operations { · 42 unmodified lines
376 const char *, const char *,391 const char *, const char *,
377 struct cifs_sb_info *);392 struct cifs_sb_info *);
378 /* query symlink target */393 /* query symlink target */
379 int (*query_symlink)(const unsigned int, struct cifs_tcon *,394 int (*query_symlink)(const unsigned int xid,
380 struct cifs_sb_info *, const char *,395 struct cifs_tcon *tcon,
381 char **, bool);396 struct cifs_sb_info *cifs_sb,
397 const char *full_path,
398 char **target_path,
399 struct kvec *rsp_iov);
382 /* open a file for non-posix mounts */400 /* open a file for non-posix mounts */
383 int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,401 int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
384 void *buf);402 void *buf);
@@ -727,8 +745,9 @@ struct TCP_Server_Info { · 342 unmodified lines
727 * primary_server holds the ref-counted745 * primary_server holds the ref-counted
728 * pointer to primary channel connection for the session.746 * pointer to primary channel connection for the session.
729 */747 */
730#define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server)748#define SERVER_IS_CHAN(server) (!!(server)->primary_server)
731 struct TCP_Server_Info *primary_server;749 struct TCP_Server_Info *primary_server;
750 __u16 channel_sequence_num; /* incremented on primary channel on each chan reconnect */
732 751
733#ifdef CONFIG_CIFS_SWN_UPCALL752#ifdef CONFIG_CIFS_SWN_UPCALL
734 bool use_swn_dstaddr;753 bool use_swn_dstaddr;
@@ -1076,7 +1095,7 @@ cap_unix(struct cifs_ses *ses) · 341 unmodified lines
1076 * inode with new info1095 * inode with new info
1077 */1096 */
1078 1097
1079#define CIFS_FATTR_DFS_REFERRAL 0x11098#define CIFS_FATTR_JUNCTION 0x1
1080#define CIFS_FATTR_DELETE_PENDING 0x21099#define CIFS_FATTR_DELETE_PENDING 0x2
1081#define CIFS_FATTR_NEED_REVAL 0x41100#define CIFS_FATTR_NEED_REVAL 0x4
1082#define CIFS_FATTR_INO_COLLISION 0x81101#define CIFS_FATTR_INO_COLLISION 0x8
@@ -1721,11 +1740,23 @@ struct cifs_mount_ctx { · 638 unmodified lines
1721 struct list_head dfs_ses_list;1740 struct list_head dfs_ses_list;
1722};1741};
1723 1742
1743static inline void __free_dfs_info_param(struct dfs_info3_param *param)
1744{
1745 kfree(param->path_name);
1746 kfree(param->node_name);
1747}
1748
1724static inline void free_dfs_info_param(struct dfs_info3_param *param)1749static inline void free_dfs_info_param(struct dfs_info3_param *param)
1750{
1751 if (param)
1752 __free_dfs_info_param(param);
1753}
1754
1755static inline void zfree_dfs_info_param(struct dfs_info3_param *param)
1725{1756{
1726 if (param) {1757 if (param) {
1727 kfree(param->path_name);1758 __free_dfs_info_param(param);
1728 kfree(param->node_name);1759 memset(param, 0, sizeof(*param));
1729 }1760 }
1730}1761}
1731 1762
@@ -2184,4 +2215,17 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable, · 452 unmodified lines
2184 }2215 }
2185}2216}
2186 2217
2218struct smb2_compound_vars {
2219 struct cifs_open_parms oparms;
2220 struct kvec rsp_iov[3];
2221 struct smb_rqst rqst[3];
2222 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
2223 struct kvec qi_iov;
2224 struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
2225 struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
2226 struct kvec close_iov;
2227 struct smb2_file_rename_info rename_info;
2228 struct smb2_file_link_info link_info;
2229};
2230
2187#endif /* _CIFS_GLOB_H */2231#endif /* _CIFS_GLOB_H */
fs/smb/client/cifsproto.h+4−5
@@ -207,6 +207,9 @@ extern struct inode *cifs_iget(struct super_block *sb, · 206 unmodified lines
207int cifs_get_inode_info(struct inode **inode, const char *full_path,207int cifs_get_inode_info(struct inode **inode, const char *full_path,
208 struct cifs_open_info_data *data, struct super_block *sb, int xid,208 struct cifs_open_info_data *data, struct super_block *sb, int xid,
209 const struct cifs_fid *fid);209 const struct cifs_fid *fid);
210bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
211 struct cifs_fattr *fattr,
212 u32 tag);
210extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,213extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
211 struct super_block *sb, unsigned int xid);214 struct super_block *sb, unsigned int xid);
212extern int cifs_get_inode_info_unix(struct inode **pinode,215extern int cifs_get_inode_info_unix(struct inode **pinode,
@@ -295,11 +298,7 @@ extern void cifs_put_tcp_session(struct TCP_Server_Info *server, · 82 unmodified lines
295 int from_reconnect);298 int from_reconnect);
296extern void cifs_put_tcon(struct cifs_tcon *tcon);299extern void cifs_put_tcon(struct cifs_tcon *tcon);
297 300
298#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)301extern void cifs_release_automount_timer(void);
299extern void cifs_dfs_release_automount_timer(void);
300#else /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
301#define cifs_dfs_release_automount_timer() do { } while (0)
302#endif /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
303 302
304void cifs_proc_init(void);303void cifs_proc_init(void);
305void cifs_proc_clean(void);304void cifs_proc_clean(void);
fs/smb/client/connect.c+11−10
@@ -154,7 +154,7 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, · 153 unmodified lines
154 int i;154 int i;
155 155
156 /* If server is a channel, select the primary channel */156 /* If server is a channel, select the primary channel */
157 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;157 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
158 158
159 spin_lock(&pserver->srv_lock);159 spin_lock(&pserver->srv_lock);
160 if (!all_channels) {160 if (!all_channels) {
@@ -202,7 +202,7 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, · 41 unmodified lines
202 cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__);202 cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__);
203 203
204 /* If server is a channel, select the primary channel */204 /* If server is a channel, select the primary channel */
205 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;205 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
206 206
207 207
208 spin_lock(&cifs_tcp_ses_lock);208 spin_lock(&cifs_tcp_ses_lock);
@@ -453,10 +453,10 @@ static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_ · 244 unmodified lines
453 453
454static int reconnect_dfs_server(struct TCP_Server_Info *server)454static int reconnect_dfs_server(struct TCP_Server_Info *server)
455{455{
456 int rc = 0;
457 struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
458 struct dfs_cache_tgt_iterator *target_hint = NULL;456 struct dfs_cache_tgt_iterator *target_hint = NULL;
457 DFS_CACHE_TGT_LIST(tl);
459 int num_targets = 0;458 int num_targets = 0;
459 int rc = 0;
460 460
461 /*461 /*
462 * Determine the number of dfs targets the referral path in @cifs_sb resolves to.462 * Determine the number of dfs targets the referral path in @cifs_sb resolves to.
@@ -911,8 +911,8 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) · 448 unmodified lines
911 return 0;911 return 0;
912}912}
913 913
914 914static noinline_for_stack void
915static void clean_demultiplex_info(struct TCP_Server_Info *server)915clean_demultiplex_info(struct TCP_Server_Info *server)
916{916{
917 int length;917 int length;
918 918
@@ -1551,7 +1551,7 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx) · 632 unmodified lines
1551 * Skip ses channels since they're only handled in lower layers1551 * Skip ses channels since they're only handled in lower layers
1552 * (e.g. cifs_send_recv).1552 * (e.g. cifs_send_recv).
1553 */1553 */
1554 if (CIFS_SERVER_IS_CHAN(server) ||1554 if (SERVER_IS_CHAN(server) ||
1555 !match_server(server, ctx, false)) {1555 !match_server(server, ctx, false)) {
1556 spin_unlock(&server->srv_lock);1556 spin_unlock(&server->srv_lock);
1557 continue;1557 continue;
@@ -1587,7 +1587,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) · 29 unmodified lines
1587 spin_unlock(&cifs_tcp_ses_lock);1587 spin_unlock(&cifs_tcp_ses_lock);
1588 1588
1589 /* For secondary channels, we pick up ref-count on the primary server */1589 /* For secondary channels, we pick up ref-count on the primary server */
1590 if (CIFS_SERVER_IS_CHAN(server))1590 if (SERVER_IS_CHAN(server))
1591 cifs_put_tcp_session(server->primary_server, from_reconnect);1591 cifs_put_tcp_session(server->primary_server, from_reconnect);
1592 1592
1593 cancel_delayed_work_sync(&server->echo);1593 cancel_delayed_work_sync(&server->echo);
@@ -1686,6 +1686,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, · 92 unmodified lines
1686 ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);1686 ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1687 tcp_ses->session_estab = false;1687 tcp_ses->session_estab = false;
1688 tcp_ses->sequence_number = 0;1688 tcp_ses->sequence_number = 0;
1689 tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */
1689 tcp_ses->reconnect_instance = 1;1690 tcp_ses->reconnect_instance = 1;
1690 tcp_ses->lstrp = jiffies;1691 tcp_ses->lstrp = jiffies;
1691 tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);1692 tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);
@@ -1792,7 +1793,7 @@ out_err_crypto_release: · 100 unmodified lines
1792 1793
1793out_err:1794out_err:
1794 if (tcp_ses) {1795 if (tcp_ses) {
1795 if (CIFS_SERVER_IS_CHAN(tcp_ses))1796 if (SERVER_IS_CHAN(tcp_ses))
1796 cifs_put_tcp_session(tcp_ses->primary_server, false);1797 cifs_put_tcp_session(tcp_ses->primary_server, false);
1797 kfree(tcp_ses->hostname);1798 kfree(tcp_ses->hostname);
1798 kfree(tcp_ses->leaf_fullpath);1799 kfree(tcp_ses->leaf_fullpath);
@@ -3813,7 +3814,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, · 2014 unmodified lines
3813 struct nls_table *nls_info)3814 struct nls_table *nls_info)
3814{3815{
3815 int rc = -ENOSYS;3816 int rc = -ENOSYS;
3816 struct TCP_Server_Info *pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;3817 struct TCP_Server_Info *pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
3817 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr;3818 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr;
3818 struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr;3819 struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr;
3819 bool is_binding = false;3820 bool is_binding = false;
fs/smb/client/dfs.c+150−121
@@ -3,7 +3,6 @@ · 2 unmodified lines
3 * Copyright (c) 2022 Paulo Alcantara <palcantara@suse.de>3 * Copyright (c) 2022 Paulo Alcantara <palcantara@suse.de>
4 */4 */
5 5
6#include <linux/namei.h>
7#include "cifsproto.h"6#include "cifsproto.h"
8#include "cifs_debug.h"7#include "cifs_debug.h"
9#include "dns_resolve.h"8#include "dns_resolve.h"
@@ -96,51 +95,134 @@ static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx) · 86 unmodified lines
96 return 0;95 return 0;
97}96}
98 97
99static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, const char *full_path,98static inline int parse_dfs_target(struct smb3_fs_context *ctx,
100 const struct dfs_cache_tgt_iterator *tit)99 struct dfs_ref_walk *rw,
100 struct dfs_info3_param *tgt)
101{
102 int rc;
103 const char *fpath = ref_walk_fpath(rw) + 1;
104
105 rc = ref_walk_get_tgt(rw, tgt);
106 if (!rc)
107 rc = dfs_parse_target_referral(fpath, tgt, ctx);
108 return rc;
109}
110
111static int set_ref_paths(struct cifs_mount_ctx *mnt_ctx,
112 struct dfs_info3_param *tgt,
113 struct dfs_ref_walk *rw)
101{114{
102 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;115 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
103 struct dfs_info3_param ref = {};116 struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
104 bool is_refsrv;117 char *ref_path, *full_path;
105 int rc, rc2;118 int rc;
106 119
107 rc = dfs_cache_get_tgt_referral(ref_path + 1, tit, &ref);120 full_path = smb3_fs_context_fullpath(ctx, CIFS_DIR_SEP(cifs_sb));
108 if (rc)121 if (IS_ERR(full_path))
122 return PTR_ERR(full_path);
123
124 if (!tgt || (tgt->server_type == DFS_TYPE_LINK &&
125 DFS_INTERLINK(tgt->flags)))
126 ref_path = dfs_get_path(cifs_sb, ctx->UNC);
127 else
128 ref_path = dfs_get_path(cifs_sb, full_path);
129 if (IS_ERR(ref_path)) {
130 rc = PTR_ERR(ref_path);
131 kfree(full_path);
109 return rc;132 return rc;
133 }
134 ref_walk_path(rw) = ref_path;
135 ref_walk_fpath(rw) = full_path;
136 return 0;
137}
110 138
111 rc = dfs_parse_target_referral(full_path + 1, &ref, ctx);139static int __dfs_referral_walk(struct cifs_mount_ctx *mnt_ctx,
112 if (rc)140 struct dfs_ref_walk *rw)
113 goto out;141{
142 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
143 struct dfs_info3_param tgt = {};
144 bool is_refsrv;
145 int rc = -ENOENT;
114 146
115 cifs_mount_put_conns(mnt_ctx);147again:
116 rc = get_session(mnt_ctx, ref_path);148 do {
117 if (rc)149 if (ref_walk_empty(rw)) {
118 goto out;150 rc = dfs_get_referral(mnt_ctx, ref_walk_path(rw) + 1,
151 NULL, ref_walk_tl(rw));
152 if (rc) {
153 rc = cifs_mount_get_tcon(mnt_ctx);
154 if (!rc)
155 rc = cifs_is_path_remote(mnt_ctx);
156 continue;
157 }
158 if (!ref_walk_num_tgts(rw)) {
159 rc = -ENOENT;
160 continue;
161 }
162 }
119 163
120 is_refsrv = !!(ref.flags & DFSREF_REFERRAL_SERVER);164 while (ref_walk_next_tgt(rw)) {
165 rc = parse_dfs_target(ctx, rw, &tgt);
166 if (rc)
167 continue;
121 168
122 rc = -EREMOTE;169 cifs_mount_put_conns(mnt_ctx);
123 if (ref.flags & DFSREF_STORAGE_SERVER) {170 rc = get_session(mnt_ctx, ref_walk_path(rw));
124 rc = cifs_mount_get_tcon(mnt_ctx);171 if (rc)
125 if (rc)172 continue;
126 goto out;
127 173
128 /* some servers may not advertise referral capability under ref.flags */174 is_refsrv = tgt.server_type == DFS_TYPE_ROOT ||
129 is_refsrv |= is_tcon_dfs(mnt_ctx->tcon);175 DFS_INTERLINK(tgt.flags);
176 ref_walk_set_tgt_hint(rw);
130 177
131 rc = cifs_is_path_remote(mnt_ctx);178 if (tgt.flags & DFSREF_STORAGE_SERVER) {
132 }179 rc = cifs_mount_get_tcon(mnt_ctx);
180 if (!rc)
181 rc = cifs_is_path_remote(mnt_ctx);
182 if (!rc)
183 break;
184 if (rc != -EREMOTE)
185 continue;
186 }
133 187
134 dfs_cache_noreq_update_tgthint(ref_path + 1, tit);188 if (is_refsrv) {
189 rc = add_root_smb_session(mnt_ctx);
190 if (rc)
191 goto out;
192 }
135 193
136 if (rc == -EREMOTE && is_refsrv) {194 rc = ref_walk_advance(rw);
137 rc2 = add_root_smb_session(mnt_ctx);195 if (!rc) {
138 if (rc2)196 rc = set_ref_paths(mnt_ctx, &tgt, rw);
139 rc = rc2;197 if (!rc) {
140 }198 rc = -EREMOTE;
199 goto again;
200 }
201 }
202 if (rc != -ELOOP)
203 goto out;
204 }
205 } while (rc && ref_walk_descend(rw));
141 206
142out:207out:
143 free_dfs_info_param(&ref);208 free_dfs_info_param(&tgt);
209 return rc;
210}
211
212static int dfs_referral_walk(struct cifs_mount_ctx *mnt_ctx)
213{
214 struct dfs_ref_walk *rw;
215 int rc;
216
217 rw = ref_walk_alloc();
218 if (IS_ERR(rw))
219 return PTR_ERR(rw);
220
221 ref_walk_init(rw);
222 rc = set_ref_paths(mnt_ctx, NULL, rw);
223 if (!rc)
224 rc = __dfs_referral_walk(mnt_ctx, rw);
225 ref_walk_free(rw);
144 return rc;226 return rc;
145}227}
146 228
@@ -148,105 +230,48 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) · 1 unmodified line
148{230{
149 struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;231 struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
150 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;232 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
151 char *ref_path = NULL, *full_path = NULL;
152 struct dfs_cache_tgt_iterator *tit;
153 struct cifs_tcon *tcon;233 struct cifs_tcon *tcon;
154 char *origin_fullpath = NULL;234 char *origin_fullpath;
155 char sep = CIFS_DIR_SEP(cifs_sb);
156 int num_links = 0;
157 int rc;235 int rc;
158 236
159 ref_path = dfs_get_path(cifs_sb, ctx->UNC);237 origin_fullpath = dfs_get_path(cifs_sb, ctx->source);
160 if (IS_ERR(ref_path))238 if (IS_ERR(origin_fullpath))
161 return PTR_ERR(ref_path);239 return PTR_ERR(origin_fullpath);
162 240
163 full_path = smb3_fs_context_fullpath(ctx, sep);241 rc = dfs_referral_walk(mnt_ctx);
164 if (IS_ERR(full_path)) {242 if (rc)
165 rc = PTR_ERR(full_path);
166 full_path = NULL;
167 goto out;243 goto out;
168 }
169 244
170 origin_fullpath = kstrdup(full_path, GFP_KERNEL);245 tcon = mnt_ctx->tcon;
171 if (!origin_fullpath) {246 spin_lock(&tcon->tc_lock);
172 rc = -ENOMEM;247 if (!tcon->origin_fullpath) {
173 goto out;248 tcon->origin_fullpath = origin_fullpath;
249 origin_fullpath = NULL;
174 }250 }
251 spin_unlock(&tcon->tc_lock);
175 252
176 do {253 if (list_empty(&tcon->dfs_ses_list)) {
177 struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);254 list_replace_init(&mnt_ctx->dfs_ses_list, &tcon->dfs_ses_list);
178 255 queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,
179 rc = dfs_get_referral(mnt_ctx, ref_path + 1, NULL, &tl);256 dfs_cache_get_ttl() * HZ);
180 if (rc) {257 } else {
181 rc = cifs_mount_get_tcon(mnt_ctx);258 dfs_put_root_smb_sessions(&mnt_ctx->dfs_ses_list);
182 if (!rc)
183 rc = cifs_is_path_remote(mnt_ctx);
184 break;
185 }
186
187 tit = dfs_cache_get_tgt_iterator(&tl);
188 if (!tit) {
189 cifs_dbg(VFS, "%s: dfs referral (%s) with no targets\n", __func__,
190 ref_path + 1);
191 rc = -ENOENT;
192 dfs_cache_free_tgts(&tl);
193 break;
194 }
195
196 do {
197 rc = get_dfs_conn(mnt_ctx, ref_path, full_path, tit);
198 if (!rc)
199 break;
200 if (rc == -EREMOTE) {
201 if (++num_links > MAX_NESTED_LINKS) {
202 rc = -ELOOP;
203 break;
204 }
205 kfree(ref_path);
206 kfree(full_path);
207 ref_path = full_path = NULL;
208
209 full_path = smb3_fs_context_fullpath(ctx, sep);
210 if (IS_ERR(full_path)) {
211 rc = PTR_ERR(full_path);
212 full_path = NULL;
213 } else {
214 ref_path = dfs_get_path(cifs_sb, full_path);
215 if (IS_ERR(ref_path)) {
216 rc = PTR_ERR(ref_path);
217 ref_path = NULL;
218 }
219 }
220 break;
221 }
222 } while ((tit = dfs_cache_get_next_tgt(&tl, tit)));
223 dfs_cache_free_tgts(&tl);
224 } while (rc == -EREMOTE);
225
226 if (!rc) {
227 tcon = mnt_ctx->tcon;
228
229 spin_lock(&tcon->tc_lock);
230 if (!tcon->origin_fullpath) {
231 tcon->origin_fullpath = origin_fullpath;
232 origin_fullpath = NULL;
233 }
234 spin_unlock(&tcon->tc_lock);
235
236 if (list_empty(&tcon->dfs_ses_list)) {
237 list_replace_init(&mnt_ctx->dfs_ses_list,
238 &tcon->dfs_ses_list);
239 queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,
240 dfs_cache_get_ttl() * HZ);
241 } else {
242 dfs_put_root_smb_sessions(&mnt_ctx->dfs_ses_list);
243 }
244 }259 }
245 260
246out:261out:
247 kfree(origin_fullpath);262 kfree(origin_fullpath);
248 kfree(ref_path);263 return rc;
249 kfree(full_path);264}
265
266/* Resolve UNC hostname in @ctx->source and set ip addr in @ctx->dstaddr */
267static int update_fs_context_dstaddr(struct smb3_fs_context *ctx)
268{
269 struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
270 int rc;
271
272 rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL);
273 if (!rc)
274 cifs_set_port(addr, ctx->port);
250 return rc;275 return rc;
251}276}
252 277
@@ -256,6 +281,10 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) · 3 unmodified lines
256 bool nodfs = ctx->nodfs;281 bool nodfs = ctx->nodfs;
257 int rc;282 int rc;
258 283
284 rc = update_fs_context_dstaddr(ctx);
285 if (rc)
286 return rc;
287
259 *isdfs = false;288 *isdfs = false;
260 rc = get_session(mnt_ctx, NULL);289 rc = get_session(mnt_ctx, NULL);
261 if (rc)290 if (rc)
@@ -426,7 +455,7 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t · 164 unmodified lines
426 /* Try to tree connect to all dfs targets */455 /* Try to tree connect to all dfs targets */
427 for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) {456 for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) {
428 const char *target = dfs_cache_get_tgt_name(tit);457 const char *target = dfs_cache_get_tgt_name(tit);
429 struct dfs_cache_tgt_list ntl = DFS_CACHE_TGT_LIST_INIT(ntl);458 DFS_CACHE_TGT_LIST(ntl);
430 459
431 kfree(share);460 kfree(share);
432 kfree(prefix);461 kfree(prefix);
@@ -520,7 +549,7 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru · 87 unmodified lines
520 int rc;549 int rc;
521 struct TCP_Server_Info *server = tcon->ses->server;550 struct TCP_Server_Info *server = tcon->ses->server;
522 const struct smb_version_operations *ops = server->ops;551 const struct smb_version_operations *ops = server->ops;
523 struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);552 DFS_CACHE_TGT_LIST(tl);
524 struct cifs_sb_info *cifs_sb = NULL;553 struct cifs_sb_info *cifs_sb = NULL;
525 struct super_block *sb = NULL;554 struct super_block *sb = NULL;
526 struct dfs_info3_param ref = {0};555 struct dfs_info3_param ref = {0};
fs/smb/client/dfs.h+104−37
@@ -9,6 +9,110 @@ · 8 unmodified lines
9#include "cifsglob.h"9#include "cifsglob.h"
10#include "fs_context.h"10#include "fs_context.h"
11#include "cifs_unicode.h"11#include "cifs_unicode.h"
12#include <linux/namei.h>
13
14#define DFS_INTERLINK(v) \
15 (((v) & DFSREF_REFERRAL_SERVER) && !((v) & DFSREF_STORAGE_SERVER))
16
17struct dfs_ref {
18 char *path;
19 char *full_path;
20 struct dfs_cache_tgt_list tl;
21 struct dfs_cache_tgt_iterator *tit;
22};
23
24struct dfs_ref_walk {
25 struct dfs_ref *ref;
26 struct dfs_ref refs[MAX_NESTED_LINKS];
27};
28
29#define ref_walk_start(w) ((w)->refs)
30#define ref_walk_end(w) (&(w)->refs[ARRAY_SIZE((w)->refs) - 1])
31#define ref_walk_cur(w) ((w)->ref)
32#define ref_walk_descend(w) (--ref_walk_cur(w) >= ref_walk_start(w))
33
34#define ref_walk_tit(w) (ref_walk_cur(w)->tit)
35#define ref_walk_empty(w) (!ref_walk_tit(w))
36#define ref_walk_path(w) (ref_walk_cur(w)->path)
37#define ref_walk_fpath(w) (ref_walk_cur(w)->full_path)
38#define ref_walk_tl(w) (&ref_walk_cur(w)->tl)
39
40static inline struct dfs_ref_walk *ref_walk_alloc(void)
41{
42 struct dfs_ref_walk *rw;
43
44 rw = kmalloc(sizeof(*rw), GFP_KERNEL);
45 if (!rw)
46 return ERR_PTR(-ENOMEM);
47 return rw;
48}
49
50static inline void ref_walk_init(struct dfs_ref_walk *rw)
51{
52 memset(rw, 0, sizeof(*rw));
53 ref_walk_cur(rw) = ref_walk_start(rw);
54}
55
56static inline void __ref_walk_free(struct dfs_ref *ref)
57{
58 kfree(ref->path);
59 kfree(ref->full_path);
60 dfs_cache_free_tgts(&ref->tl);
61 memset(ref, 0, sizeof(*ref));
62}
63
64static inline void ref_walk_free(struct dfs_ref_walk *rw)
65{
66 struct dfs_ref *ref = ref_walk_start(rw);
67
68 for (; ref <= ref_walk_end(rw); ref++)
69 __ref_walk_free(ref);
70 kfree(rw);
71}
72
73static inline int ref_walk_advance(struct dfs_ref_walk *rw)
74{
75 struct dfs_ref *ref = ref_walk_cur(rw) + 1;
76
77 if (ref > ref_walk_end(rw))
78 return -ELOOP;
79 __ref_walk_free(ref);
80 ref_walk_cur(rw) = ref;
81 return 0;
82}
83
84static inline struct dfs_cache_tgt_iterator *
85ref_walk_next_tgt(struct dfs_ref_walk *rw)
86{
87 struct dfs_cache_tgt_iterator *tit;
88 struct dfs_ref *ref = ref_walk_cur(rw);
89
90 if (!ref->tit)
91 tit = dfs_cache_get_tgt_iterator(&ref->tl);
92 else
93 tit = dfs_cache_get_next_tgt(&ref->tl, ref->tit);
94 ref->tit = tit;
95 return tit;
96}
97
98static inline int ref_walk_get_tgt(struct dfs_ref_walk *rw,
99 struct dfs_info3_param *tgt)
100{
101 zfree_dfs_info_param(tgt);
102 return dfs_cache_get_tgt_referral(ref_walk_path(rw) + 1,
103 ref_walk_tit(rw), tgt);
104}
105
106static inline int ref_walk_num_tgts(struct dfs_ref_walk *rw)
107{
108 return dfs_cache_get_nr_tgts(ref_walk_tl(rw));
109}
110
111static inline void ref_walk_set_tgt_hint(struct dfs_ref_walk *rw)
112{
113 dfs_cache_noreq_update_tgthint(ref_walk_path(rw) + 1,
114 ref_walk_tit(rw));
115}
12 116
13struct dfs_root_ses {117struct dfs_root_ses {
14 struct list_head list;118 struct list_head list;
@@ -34,43 +138,6 @@ static inline int dfs_get_referral(struct cifs_mount_ctx *mnt_ctx, const char *p · 19 unmodified lines
34 cifs_remap(cifs_sb), path, ref, tl);138 cifs_remap(cifs_sb), path, ref, tl);
35}139}
36 140
37/* Return DFS full path out of a dentry set for automount */
38static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page)
39{
40 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
41 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
42 size_t len;
43 char *s;
44
45 spin_lock(&tcon->tc_lock);
46 if (unlikely(!tcon->origin_fullpath)) {
47 spin_unlock(&tcon->tc_lock);
48 return ERR_PTR(-EREMOTE);
49 }
50 spin_unlock(&tcon->tc_lock);
51
52 s = dentry_path_raw(dentry, page, PATH_MAX);
53 if (IS_ERR(s))
54 return s;
55 /* for root, we want "" */
56 if (!s[1])
57 s++;
58
59 spin_lock(&tcon->tc_lock);
60 len = strlen(tcon->origin_fullpath);
61 if (s < (char *)page + len) {
62 spin_unlock(&tcon->tc_lock);
63 return ERR_PTR(-ENAMETOOLONG);
64 }
65
66 s -= len;
67 memcpy(s, tcon->origin_fullpath, len);
68 spin_unlock(&tcon->tc_lock);
69 convert_delimiter(s, '/');
70
71 return s;
72}
73
74static inline void dfs_put_root_smb_sessions(struct list_head *head)141static inline void dfs_put_root_smb_sessions(struct list_head *head)
75{142{
76 struct dfs_root_ses *root, *tmp;143 struct dfs_root_ses *root, *tmp;
fs/smb/client/dfs_cache.c+4−6
@@ -29,8 +29,6 @@ · 28 unmodified lines
29#define CACHE_MIN_TTL 120 /* 2 minutes */29#define CACHE_MIN_TTL 120 /* 2 minutes */
30#define CACHE_DEFAULT_TTL 300 /* 5 minutes */30#define CACHE_DEFAULT_TTL 300 /* 5 minutes */
31 31
32#define IS_DFS_INTERLINK(v) (((v) & DFSREF_REFERRAL_SERVER) && !((v) & DFSREF_STORAGE_SERVER))
33
34struct cache_dfs_tgt {32struct cache_dfs_tgt {
35 char *name;33 char *name;
36 int path_consumed;34 int path_consumed;
@@ -174,7 +172,7 @@ static int dfscache_proc_show(struct seq_file *m, void *v) · 137 unmodified lines
174 "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",172 "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",
175 ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link",173 ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link",
176 ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags,174 ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags,
177 IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",175 DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",
178 ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no");176 ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no");
179 177
180 list_for_each_entry(t, &ce->tlist, list) {178 list_for_each_entry(t, &ce->tlist, list) {
@@ -243,7 +241,7 @@ static inline void dump_ce(const struct cache_entry *ce) · 62 unmodified lines
243 ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl,241 ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl,
244 ce->etime.tv_nsec,242 ce->etime.tv_nsec,
245 ce->hdr_flags, ce->ref_flags,243 ce->hdr_flags, ce->ref_flags,
246 IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",244 DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",
247 ce->path_consumed,245 ce->path_consumed,
248 cache_entry_expired(ce) ? "yes" : "no");246 cache_entry_expired(ce) ? "yes" : "no");
249 dump_tgts(ce);247 dump_tgts(ce);
@@ -1177,9 +1175,9 @@ static bool is_ses_good(struct cifs_ses *ses) · 927 unmodified lines
1177/* Refresh dfs referral of tcon and mark it for reconnect if needed */1175/* Refresh dfs referral of tcon and mark it for reconnect if needed */
1178static int __refresh_tcon(const char *path, struct cifs_ses *ses, bool force_refresh)1176static int __refresh_tcon(const char *path, struct cifs_ses *ses, bool force_refresh)
1179{1177{
1180 struct dfs_cache_tgt_list old_tl = DFS_CACHE_TGT_LIST_INIT(old_tl);
1181 struct dfs_cache_tgt_list new_tl = DFS_CACHE_TGT_LIST_INIT(new_tl);
1182 struct TCP_Server_Info *server = ses->server;1178 struct TCP_Server_Info *server = ses->server;
1179 DFS_CACHE_TGT_LIST(old_tl);
1180 DFS_CACHE_TGT_LIST(new_tl);
1183 bool needs_refresh = false;1181 bool needs_refresh = false;
1184 struct cache_entry *ce;1182 struct cache_entry *ce;
1185 unsigned int xid;1183 unsigned int xid;
fs/smb/client/dfs_cache.h+8−4
@@ -16,7 +16,11 @@ · 15 unmodified lines
16extern struct workqueue_struct *dfscache_wq;16extern struct workqueue_struct *dfscache_wq;
17extern atomic_t dfs_cache_ttl;17extern atomic_t dfs_cache_ttl;
18 18
19#define DFS_CACHE_TGT_LIST_INIT(var) { .tl_numtgts = 0, .tl_list = LIST_HEAD_INIT((var).tl_list), }19#define DFS_CACHE_TGT_LIST_INIT(var) \
20 { .tl_numtgts = 0, .tl_list = LIST_HEAD_INIT((var).tl_list), }
21
22#define DFS_CACHE_TGT_LIST(var) \
23 struct dfs_cache_tgt_list var = DFS_CACHE_TGT_LIST_INIT(var)
20 24
21struct dfs_cache_tgt_list {25struct dfs_cache_tgt_list {
22 int tl_numtgts;26 int tl_numtgts;
@@ -51,8 +55,8 @@ static inline struct dfs_cache_tgt_iterator * · 28 unmodified lines
51dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl,55dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl,
52 struct dfs_cache_tgt_iterator *it)56 struct dfs_cache_tgt_iterator *it)
53{57{
54 if (!tl || list_empty(&tl->tl_list) || !it ||58 if (!tl || !tl->tl_numtgts || list_empty(&tl->tl_list) ||
55 list_is_last(&it->it_list, &tl->tl_list))59 !it || list_is_last(&it->it_list, &tl->tl_list))
56 return NULL;60 return NULL;
57 return list_next_entry(it, it_list);61 return list_next_entry(it, it_list);
58}62}
@@ -71,7 +75,7 @@ static inline void dfs_cache_free_tgts(struct dfs_cache_tgt_list *tl) · 12 unmodified lines
71{75{
72 struct dfs_cache_tgt_iterator *it, *nit;76 struct dfs_cache_tgt_iterator *it, *nit;
73 77
74 if (!tl || list_empty(&tl->tl_list))78 if (!tl || !tl->tl_numtgts || list_empty(&tl->tl_list))
75 return;79 return;
76 list_for_each_entry_safe(it, nit, &tl->tl_list, it_list) {80 list_for_each_entry_safe(it, nit, &tl->tl_list, it_list) {
77 list_del(&it->it_list);81 list_del(&it->it_list);
fs/smb/client/dir.c+2−2
@@ -797,7 +797,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags) · 796 unmodified lines
797 797
798const struct dentry_operations cifs_dentry_ops = {798const struct dentry_operations cifs_dentry_ops = {
799 .d_revalidate = cifs_d_revalidate,799 .d_revalidate = cifs_d_revalidate,
800 .d_automount = cifs_dfs_d_automount,800 .d_automount = cifs_d_automount,
801/* d_delete: cifs_d_delete, */ /* not needed except for debugging */801/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
802};802};
803 803
@@ -872,5 +872,5 @@ const struct dentry_operations cifs_ci_dentry_ops = { · 68 unmodified lines
872 .d_revalidate = cifs_d_revalidate,872 .d_revalidate = cifs_d_revalidate,
873 .d_hash = cifs_ci_hash,873 .d_hash = cifs_ci_hash,
874 .d_compare = cifs_ci_compare,874 .d_compare = cifs_ci_compare,
875 .d_automount = cifs_dfs_d_automount,875 .d_automount = cifs_d_automount,
876};876};
fs/smb/client/inode.c+284−214
@@ -58,13 +58,9 @@ static void cifs_set_ops(struct inode *inode) · 57 unmodified lines
58 inode->i_data.a_ops = &cifs_addr_ops;58 inode->i_data.a_ops = &cifs_addr_ops;
59 break;59 break;
60 case S_IFDIR:60 case S_IFDIR:
61#ifdef CONFIG_CIFS_DFS_UPCALL
62 if (IS_AUTOMOUNT(inode)) {61 if (IS_AUTOMOUNT(inode)) {
63 inode->i_op = &cifs_dfs_referral_inode_operations;62 inode->i_op = &cifs_namespace_inode_operations;
64 } else {63 } else {
65#else /* NO DFS support, treat as a directory */
66 {
67#endif
68 inode->i_op = &cifs_dir_inode_ops;64 inode->i_op = &cifs_dir_inode_ops;
69 inode->i_fop = &cifs_dir_ops;65 inode->i_fop = &cifs_dir_ops;
70 }66 }
@@ -218,7 +214,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) · 147 unmodified lines
218 }214 }
219 spin_unlock(&inode->i_lock);215 spin_unlock(&inode->i_lock);
220 216
221 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)217 if (fattr->cf_flags & CIFS_FATTR_JUNCTION)
222 inode->i_flags |= S_AUTOMOUNT;218 inode->i_flags |= S_AUTOMOUNT;
223 if (inode->i_state & I_NEW)219 if (inode->i_state & I_NEW)
224 cifs_set_ops(inode);220 cifs_set_ops(inode);
@@ -327,14 +323,14 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, · 102 unmodified lines
327 *323 *
328 * Needed to setup cifs_fattr data for the directory which is the324 * Needed to setup cifs_fattr data for the directory which is the
329 * junction to the new submount (ie to setup the fake directory325 * junction to the new submount (ie to setup the fake directory
330 * which represents a DFS referral).326 * which represents a DFS referral or reparse mount point).
331 */327 */
332static void328static void cifs_create_junction_fattr(struct cifs_fattr *fattr,
333cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)329 struct super_block *sb)
334{330{
335 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);331 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
336 332
337 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");333 cifs_dbg(FYI, "%s: creating fake fattr\n", __func__);
338 334
339 memset(fattr, 0, sizeof(*fattr));335 memset(fattr, 0, sizeof(*fattr));
340 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;336 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
@@ -343,7 +339,33 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) · 2 unmodified lines
343 ktime_get_coarse_real_ts64(&fattr->cf_mtime);339 ktime_get_coarse_real_ts64(&fattr->cf_mtime);
344 fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;340 fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
345 fattr->cf_nlink = 2;341 fattr->cf_nlink = 2;
346 fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;342 fattr->cf_flags = CIFS_FATTR_JUNCTION;
343}
344
345/* Update inode with final fattr data */
346static int update_inode_info(struct super_block *sb,
347 struct cifs_fattr *fattr,
348 struct inode **inode)
349{
350 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
351 int rc = 0;
352
353 if (!*inode) {
354 *inode = cifs_iget(sb, fattr);
355 if (!*inode)
356 rc = -ENOMEM;
357 return rc;
358 }
359 /* We already have inode, update it.
360 *
361 * If file type or uniqueid is different, return error.
362 */
363 if (unlikely((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
364 CIFS_I(*inode)->uniqueid != fattr->cf_uniqueid)) {
365 CIFS_I(*inode)->time = 0; /* force reval */
366 return -ESTALE;
367 }
368 return cifs_fattr_to_inode(*inode, fattr);
347}369}
348 370
349#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY371#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
@@ -373,7 +395,7 @@ cifs_get_file_info_unix(struct file *filp) · 23 unmodified lines
373 if (!rc) {395 if (!rc) {
374 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);396 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
375 } else if (rc == -EREMOTE) {397 } else if (rc == -EREMOTE) {
376 cifs_create_dfs_fattr(&fattr, inode->i_sb);398 cifs_create_junction_fattr(&fattr, inode->i_sb);
377 rc = 0;399 rc = 0;
378 } else400 } else
379 goto cifs_gfiunix_out;401 goto cifs_gfiunix_out;
@@ -385,17 +407,18 @@ cifs_gfiunix_out: · 5 unmodified lines
385 return rc;407 return rc;
386}408}
387 409
388int cifs_get_inode_info_unix(struct inode **pinode,410static int cifs_get_unix_fattr(const unsigned char *full_path,
389 const unsigned char *full_path,411 struct super_block *sb,
390 struct super_block *sb, unsigned int xid)412 struct cifs_fattr *fattr,
413 struct inode **pinode,
414 const unsigned int xid)
391{415{
392 int rc;416 struct TCP_Server_Info *server;
417 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
393 FILE_UNIX_BASIC_INFO find_data;418 FILE_UNIX_BASIC_INFO find_data;
394 struct cifs_fattr fattr;
395 struct cifs_tcon *tcon;419 struct cifs_tcon *tcon;
396 struct TCP_Server_Info *server;
397 struct tcon_link *tlink;420 struct tcon_link *tlink;
398 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);421 int rc, tmprc;
399 422
400 cifs_dbg(FYI, "Getting info on %s\n", full_path);423 cifs_dbg(FYI, "Getting info on %s\n", full_path);
401 424
@@ -412,59 +435,61 @@ int cifs_get_inode_info_unix(struct inode **pinode, · 10 unmodified lines
412 cifs_put_tlink(tlink);435 cifs_put_tlink(tlink);
413 436
414 if (!rc) {437 if (!rc) {
415 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);438 cifs_unix_basic_to_fattr(fattr, &find_data, cifs_sb);
416 } else if (rc == -EREMOTE) {439 } else if (rc == -EREMOTE) {
417 cifs_create_dfs_fattr(&fattr, sb);440 cifs_create_junction_fattr(fattr, sb);
418 rc = 0;441 rc = 0;
419 } else {442 } else {
420 return rc;443 return rc;
421 }444 }
422 445
446 if (!*pinode)
447 cifs_fill_uniqueid(sb, fattr);
448
423 /* check for Minshall+French symlinks */449 /* check for Minshall+French symlinks */
424 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {450 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
425 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,451 tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
426 full_path);452 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
427 if (tmprc)
428 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
429 }453 }
430 454
431 if (S_ISLNK(fattr.cf_mode) && !fattr.cf_symlink_target) {455 if (S_ISLNK(fattr->cf_mode) && !fattr->cf_symlink_target) {
432 if (!server->ops->query_symlink)456 if (!server->ops->query_symlink)
433 return -EOPNOTSUPP;457 return -EOPNOTSUPP;
434 rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path,458 rc = server->ops->query_symlink(xid, tcon,
435 &fattr.cf_symlink_target, false);459 cifs_sb, full_path,
436 if (rc) {460 &fattr->cf_symlink_target,
437 cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);461 NULL);
438 goto cgiiu_exit;462 cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
439 }
440 }463 }
464 return rc;
465}
441 466
442 if (*pinode == NULL) {467int cifs_get_inode_info_unix(struct inode **pinode,
443 /* get new inode */468 const unsigned char *full_path,
444 cifs_fill_uniqueid(sb, &fattr);469 struct super_block *sb, unsigned int xid)
445 *pinode = cifs_iget(sb, &fattr);470{
446 if (!*pinode)471 struct cifs_fattr fattr = {};
447 rc = -ENOMEM;472 int rc;
448 } else {
449 /* we already have inode, update it */
450
451 /* if uniqueid is different, return error */
452 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
453 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
454 CIFS_I(*pinode)->time = 0; /* force reval */
455 rc = -ESTALE;
456 goto cgiiu_exit;
457 }
458 473
459 /* if filetype is different, return error */474 rc = cifs_get_unix_fattr(full_path, sb, &fattr, pinode, xid);
460 rc = cifs_fattr_to_inode(*pinode, &fattr);475 if (rc)
461 }476 goto out;
462 477
463cgiiu_exit:478 rc = update_inode_info(sb, &fattr, pinode);
479out:
464 kfree(fattr.cf_symlink_target);480 kfree(fattr.cf_symlink_target);
465 return rc;481 return rc;
466}482}
467#else483#else
484static inline int cifs_get_unix_fattr(const unsigned char *full_path,
485 struct super_block *sb,
486 struct cifs_fattr *fattr,
487 struct inode **pinode,
488 const unsigned int xid)
489{
490 return -EOPNOTSUPP;
491}
492
468int cifs_get_inode_info_unix(struct inode **pinode,493int cifs_get_inode_info_unix(struct inode **pinode,
469 const unsigned char *full_path,494 const unsigned char *full_path,
470 struct super_block *sb, unsigned int xid)495 struct super_block *sb, unsigned int xid)
@@ -632,10 +657,11 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, · 161 unmodified lines
632}657}
633 658
634/* Fill a cifs_fattr struct with info from POSIX info struct */659/* Fill a cifs_fattr struct with info from POSIX info struct */
635static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,660static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
661 struct cifs_open_info_data *data,
636 struct cifs_sid *owner,662 struct cifs_sid *owner,
637 struct cifs_sid *group,663 struct cifs_sid *group,
638 struct super_block *sb, bool adjust_tz, bool symlink)664 struct super_block *sb)
639{665{
640 struct smb311_posix_qinfo *info = &data->posix_fi;666 struct smb311_posix_qinfo *info = &data->posix_fi;
641 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);667 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -655,7 +681,7 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_ope · 13 unmodified lines
655 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);681 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
656 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);682 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
657 683
658 if (adjust_tz) {684 if (data->adjust_tz) {
659 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;685 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
660 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;686 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
661 }687 }
@@ -669,7 +695,7 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_ope · 7 unmodified lines
669 /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */695 /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
670 /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */696 /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */
671 697
672 if (symlink) {698 if (data->symlink) {
673 fattr->cf_mode |= S_IFLNK;699 fattr->cf_mode |= S_IFLNK;
674 fattr->cf_dtype = DT_LNK;700 fattr->cf_dtype = DT_LNK;
675 fattr->cf_symlink_target = data->symlink_target;701 fattr->cf_symlink_target = data->symlink_target;
@@ -690,9 +716,46 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_ope · 14 unmodified lines
690 fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);716 fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
691}717}
692 718
693static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,719bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
694 struct super_block *sb, bool adjust_tz, bool symlink,720 struct cifs_fattr *fattr,
695 u32 reparse_tag)721 u32 tag)
722{
723 switch (tag) {
724 case IO_REPARSE_TAG_LX_SYMLINK:
725 fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
726 fattr->cf_dtype = DT_LNK;
727 break;
728 case IO_REPARSE_TAG_LX_FIFO:
729 fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
730 fattr->cf_dtype = DT_FIFO;
731 break;
732 case IO_REPARSE_TAG_AF_UNIX:
733 fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
734 fattr->cf_dtype = DT_SOCK;
735 break;
736 case IO_REPARSE_TAG_LX_CHR:
737 fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
738 fattr->cf_dtype = DT_CHR;
739 break;
740 case IO_REPARSE_TAG_LX_BLK:
741 fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
742 fattr->cf_dtype = DT_BLK;
743 break;
744 case 0: /* SMB1 symlink */
745 case IO_REPARSE_TAG_SYMLINK:
746 case IO_REPARSE_TAG_NFS:
747 fattr->cf_mode = S_IFLNK;
748 fattr->cf_dtype = DT_LNK;
749 break;
750 default:
751 return false;
752 }
753 return true;
754}
755
756static void cifs_open_info_to_fattr(struct cifs_fattr *fattr,
757 struct cifs_open_info_data *data,
758 struct super_block *sb)
696{759{
697 struct smb2_file_all_info *info = &data->fi;760 struct smb2_file_all_info *info = &data->fi;
698 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);761 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -711,7 +774,7 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_i · 12 unmodified lines
711 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);774 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
712 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);775 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
713 776
714 if (adjust_tz) {777 if (data->adjust_tz) {
715 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;778 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
716 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;779 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
717 }780 }
@@ -719,28 +782,13 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_i · 1 unmodified line
719 fattr->cf_eof = le64_to_cpu(info->EndOfFile);782 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
720 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);783 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
721 fattr->cf_createtime = le64_to_cpu(info->CreationTime);784 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
722
723 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);785 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
724 if (reparse_tag == IO_REPARSE_TAG_LX_SYMLINK) {786
725 fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;787 if (cifs_open_data_reparse(data) &&
726 fattr->cf_dtype = DT_LNK;788 cifs_reparse_point_to_fattr(cifs_sb, fattr, data->reparse_tag))
727 } else if (reparse_tag == IO_REPARSE_TAG_LX_FIFO) {789 goto out_reparse;
728 fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;790
729 fattr->cf_dtype = DT_FIFO;791 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
730 } else if (reparse_tag == IO_REPARSE_TAG_AF_UNIX) {
731 fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
732 fattr->cf_dtype = DT_SOCK;
733 } else if (reparse_tag == IO_REPARSE_TAG_LX_CHR) {
734 fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
735 fattr->cf_dtype = DT_CHR;
736 } else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) {
737 fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
738 fattr->cf_dtype = DT_BLK;
739 } else if (symlink || reparse_tag == IO_REPARSE_TAG_SYMLINK ||
740 reparse_tag == IO_REPARSE_TAG_NFS) {
741 fattr->cf_mode = S_IFLNK;
742 fattr->cf_dtype = DT_LNK;
743 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
744 fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;792 fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
745 fattr->cf_dtype = DT_DIR;793 fattr->cf_dtype = DT_DIR;
746 /*794 /*
@@ -769,6 +817,7 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_i · 22 unmodified lines
769 }817 }
770 }818 }
771 819
820out_reparse:
772 if (S_ISLNK(fattr->cf_mode)) {821 if (S_ISLNK(fattr->cf_mode)) {
773 fattr->cf_symlink_target = data->symlink_target;822 fattr->cf_symlink_target = data->symlink_target;
774 data->symlink_target = NULL;823 data->symlink_target = NULL;
@@ -789,8 +838,6 @@ cifs_get_file_info(struct file *filp) · 14 unmodified lines
789 struct cifsFileInfo *cfile = filp->private_data;838 struct cifsFileInfo *cfile = filp->private_data;
790 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);839 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
791 struct TCP_Server_Info *server = tcon->ses->server;840 struct TCP_Server_Info *server = tcon->ses->server;
792 bool symlink = false;
793 u32 tag = 0;
794 841
795 if (!server->ops->query_file_info)842 if (!server->ops->query_file_info)
796 return -ENOSYS;843 return -ENOSYS;
@@ -800,14 +847,15 @@ cifs_get_file_info(struct file *filp) · 3 unmodified lines
800 switch (rc) {847 switch (rc) {
801 case 0:848 case 0:
802 /* TODO: add support to query reparse tag */849 /* TODO: add support to query reparse tag */
850 data.adjust_tz = false;
803 if (data.symlink_target) {851 if (data.symlink_target) {
804 symlink = true;852 data.symlink = true;
805 tag = IO_REPARSE_TAG_SYMLINK;853 data.reparse_tag = IO_REPARSE_TAG_SYMLINK;
806 }854 }
807 cifs_open_info_to_fattr(&fattr, &data, inode->i_sb, false, symlink, tag);855 cifs_open_info_to_fattr(&fattr, &data, inode->i_sb);
808 break;856 break;
809 case -EREMOTE:857 case -EREMOTE:
810 cifs_create_dfs_fattr(&fattr, inode->i_sb);858 cifs_create_junction_fattr(&fattr, inode->i_sb);
811 rc = 0;859 rc = 0;
812 break;860 break;
813 case -EOPNOTSUPP:861 case -EOPNOTSUPP:
@@ -960,22 +1008,66 @@ static inline bool is_inode_cache_good(struct inode *ino) · 146 unmodified lines
960 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;1008 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
961}1009}
962 1010
963int cifs_get_inode_info(struct inode **inode, const char *full_path,1011static int reparse_info_to_fattr(struct cifs_open_info_data *data,
964 struct cifs_open_info_data *data, struct super_block *sb, int xid,1012 struct super_block *sb,
965 const struct cifs_fid *fid)1013 const unsigned int xid,
1014 struct cifs_tcon *tcon,
1015 const char *full_path,
1016 struct cifs_fattr *fattr)
966{1017{
1018 struct TCP_Server_Info *server = tcon->ses->server;
1019 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1020 struct kvec rsp_iov, *iov = NULL;
1021 int rsp_buftype = CIFS_NO_BUFFER;
1022 u32 tag = data->reparse_tag;
1023 int rc = 0;
1024
1025 if (!tag && server->ops->query_reparse_point) {
1026 rc = server->ops->query_reparse_point(xid, tcon, cifs_sb,
1027 full_path, &tag,
1028 &rsp_iov, &rsp_buftype);
1029 if (!rc)
1030 iov = &rsp_iov;
1031 }
1032 switch ((data->reparse_tag = tag)) {
1033 case 0: /* SMB1 symlink */
1034 iov = NULL;
1035 fallthrough;
1036 case IO_REPARSE_TAG_NFS:
1037 case IO_REPARSE_TAG_SYMLINK:
1038 if (!data->symlink_target && server->ops->query_symlink) {
1039 rc = server->ops->query_symlink(xid, tcon,
1040 cifs_sb, full_path,
1041 &data->symlink_target,
1042 iov);
1043 }
1044 break;
1045 case IO_REPARSE_TAG_MOUNT_POINT:
1046 cifs_create_junction_fattr(fattr, sb);
1047 goto out;
1048 }
1049
1050 cifs_open_info_to_fattr(fattr, data, sb);
1051out:
1052 free_rsp_buf(rsp_buftype, rsp_iov.iov_base);
1053 return rc;
1054}
1055
1056static int cifs_get_fattr(struct cifs_open_info_data *data,
1057 struct super_block *sb, int xid,
1058 const struct cifs_fid *fid,
1059 struct cifs_fattr *fattr,
1060 struct inode **inode,
1061 const char *full_path)
1062{
1063 struct cifs_open_info_data tmp_data = {};
967 struct cifs_tcon *tcon;1064 struct cifs_tcon *tcon;
968 struct TCP_Server_Info *server;1065 struct TCP_Server_Info *server;
969 struct tcon_link *tlink;1066 struct tcon_link *tlink;
970 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);1067 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
971 bool adjust_tz = false;
972 struct cifs_fattr fattr = {0};
973 bool is_reparse_point = false;
974 struct cifs_open_info_data tmp_data = {};
975 void *smb1_backup_rsp_buf = NULL;1068 void *smb1_backup_rsp_buf = NULL;
976 int rc = 0;1069 int rc = 0;
977 int tmprc = 0;1070 int tmprc = 0;
978 __u32 reparse_tag = 0;
979 1071
980 tlink = cifs_sb_tlink(cifs_sb);1072 tlink = cifs_sb_tlink(cifs_sb);
981 if (IS_ERR(tlink))1073 if (IS_ERR(tlink))
@@ -988,12 +1080,8 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path, · 6 unmodified lines
988 */1080 */
989 1081
990 if (!data) {1082 if (!data) {
991 if (is_inode_cache_good(*inode)) {1083 rc = server->ops->query_path_info(xid, tcon, cifs_sb,
992 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");1084 full_path, &tmp_data);
993 goto out;
994 }
995 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, &tmp_data,
996 &adjust_tz, &is_reparse_point);
997 data = &tmp_data;1085 data = &tmp_data;
998 }1086 }
999 1087
@@ -1008,28 +1096,16 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path, · 8 unmodified lines
1008 * since we have to check if its reparse tag matches a known1096 * since we have to check if its reparse tag matches a known
1009 * special file type e.g. symlink or fifo or char etc.1097 * special file type e.g. symlink or fifo or char etc.
1010 */1098 */
1011 if (is_reparse_point && data->symlink_target) {1099 if (cifs_open_data_reparse(data)) {
1012 reparse_tag = IO_REPARSE_TAG_SYMLINK;1100 rc = reparse_info_to_fattr(data, sb, xid, tcon,
1013 } else if ((le32_to_cpu(data->fi.Attributes) & ATTR_REPARSE) &&1101 full_path, fattr);
1014 server->ops->query_reparse_tag) {1102 } else {
1015 tmprc = server->ops->query_reparse_tag(xid, tcon, cifs_sb, full_path,1103 cifs_open_info_to_fattr(fattr, data, sb);
1016 &reparse_tag);
1017 if (tmprc)
1018 cifs_dbg(FYI, "%s: query_reparse_tag: rc = %d\n", __func__, tmprc);
1019 if (server->ops->query_symlink) {
1020 tmprc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path,
1021 &data->symlink_target,
1022 is_reparse_point);
1023 if (tmprc)
1024 cifs_dbg(FYI, "%s: query_symlink: rc = %d\n", __func__,
1025 tmprc);
1026 }
1027 }1104 }
1028 cifs_open_info_to_fattr(&fattr, data, sb, adjust_tz, is_reparse_point, reparse_tag);
1029 break;1105 break;
1030 case -EREMOTE:1106 case -EREMOTE:
1031 /* DFS link, no metadata available on this server */1107 /* DFS link, no metadata available on this server */
1032 cifs_create_dfs_fattr(&fattr, sb);1108 cifs_create_junction_fattr(fattr, sb);
1033 rc = 0;1109 rc = 0;
1034 break;1110 break;
1035 case -EACCES:1111 case -EACCES:
@@ -1059,8 +1135,8 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path, · 23 unmodified lines
1059 fdi = (FILE_DIRECTORY_INFO *)fi;1135 fdi = (FILE_DIRECTORY_INFO *)fi;
1060 si = (SEARCH_ID_FULL_DIR_INFO *)fi;1136 si = (SEARCH_ID_FULL_DIR_INFO *)fi;
1061 1137
1062 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);1138 cifs_dir_info_to_fattr(fattr, fdi, cifs_sb);
1063 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);1139 fattr->cf_uniqueid = le64_to_cpu(si->UniqueId);
1064 /* uniqueid set, skip get inum step */1140 /* uniqueid set, skip get inum step */
1065 goto handle_mnt_opt;1141 goto handle_mnt_opt;
1066 } else {1142 } else {
@@ -1077,10 +1153,10 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path, · 10 unmodified lines
1077 }1153 }
1078 1154
1079 /*1155 /*
1080 * 3. Get or update inode number (fattr.cf_uniqueid)1156 * 3. Get or update inode number (fattr->cf_uniqueid)
1081 */1157 */
1082 1158
1083 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);1159 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, fattr);
1084 1160
1085 /*1161 /*
1086 * 4. Tweak fattr based on mount options1162 * 4. Tweak fattr based on mount options
@@ -1089,17 +1165,17 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path, · 2 unmodified lines
1089handle_mnt_opt:1165handle_mnt_opt:
1090#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */1166#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
1091 /* query for SFU type info if supported and needed */1167 /* query for SFU type info if supported and needed */
1092 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&1168 if ((fattr->cf_cifsattrs & ATTR_SYSTEM) &&
1093 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {1169 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
1094 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);1170 tmprc = cifs_sfu_type(fattr, full_path, cifs_sb, xid);
1095 if (tmprc)1171 if (tmprc)
1096 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);1172 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
1097 }1173 }
1098 1174
1099 /* fill in 0777 bits from ACL */1175 /* fill in 0777 bits from ACL */
1100 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {1176 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
1101 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,1177 rc = cifs_acl_to_fattr(cifs_sb, fattr, *inode,
1102 full_path, fid);1178 true, full_path, fid);
1103 if (rc == -EREMOTE)1179 if (rc == -EREMOTE)
1104 rc = 0;1180 rc = 0;
1105 if (rc) {1181 if (rc) {
@@ -1108,8 +1184,8 @@ handle_mnt_opt: · 2 unmodified lines
1108 goto out;1184 goto out;
1109 }1185 }
1110 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {1186 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
1111 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,1187 rc = cifs_acl_to_fattr(cifs_sb, fattr, *inode,
1112 full_path, fid);1188 false, full_path, fid);
1113 if (rc == -EREMOTE)1189 if (rc == -EREMOTE)
1114 rc = 0;1190 rc = 0;
1115 if (rc) {1191 if (rc) {
@@ -1121,60 +1197,57 @@ handle_mnt_opt: · 5 unmodified lines
1121 1197
1122 /* fill in remaining high mode bits e.g. SUID, VTX */1198 /* fill in remaining high mode bits e.g. SUID, VTX */
1123 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)1199 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
1124 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);1200 cifs_sfu_mode(fattr, full_path, cifs_sb, xid);
1125 1201
1126 /* check for Minshall+French symlinks */1202 /* check for Minshall+French symlinks */
1127 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {1203 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1128 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,1204 tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
1129 full_path);1205 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1130 if (tmprc)
1131 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1132 }1206 }
1133 1207
1134 /*
1135 * 5. Update inode with final fattr data
1136 */
1137
1138 if (!*inode) {
1139 *inode = cifs_iget(sb, &fattr);
1140 if (!*inode)
1141 rc = -ENOMEM;
1142 } else {
1143 /* we already have inode, update it */
1144
1145 /* if uniqueid is different, return error */
1146 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1147 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1148 CIFS_I(*inode)->time = 0; /* force reval */
1149 rc = -ESTALE;
1150 goto out;
1151 }
1152 /* if filetype is different, return error */
1153 rc = cifs_fattr_to_inode(*inode, &fattr);
1154 }
1155out:1208out:
1156 cifs_buf_release(smb1_backup_rsp_buf);1209 cifs_buf_release(smb1_backup_rsp_buf);
1157 cifs_put_tlink(tlink);1210 cifs_put_tlink(tlink);
1158 cifs_free_open_info(&tmp_data);1211 cifs_free_open_info(&tmp_data);
1212 return rc;
1213}
1214
1215int cifs_get_inode_info(struct inode **inode,
1216 const char *full_path,
1217 struct cifs_open_info_data *data,
1218 struct super_block *sb, int xid,
1219 const struct cifs_fid *fid)
1220{
1221 struct cifs_fattr fattr = {};
1222 int rc;
1223
1224 if (is_inode_cache_good(*inode)) {
1225 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1226 return 0;
1227 }
1228
1229 rc = cifs_get_fattr(data, sb, xid, fid, &fattr, inode, full_path);
1230 if (rc)
1231 goto out;
1232
1233 rc = update_inode_info(sb, &fattr, inode);
1234out:
1159 kfree(fattr.cf_symlink_target);1235 kfree(fattr.cf_symlink_target);
1160 return rc;1236 return rc;
1161}1237}
1162 1238
1163int1239static int smb311_posix_get_fattr(struct cifs_fattr *fattr,
1164smb311_posix_get_inode_info(struct inode **inode,1240 const char *full_path,
1165 const char *full_path,1241 struct super_block *sb,
1166 struct super_block *sb, unsigned int xid)1242 const unsigned int xid)
1167{1243{
1244 struct cifs_open_info_data data = {};
1245 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1168 struct cifs_tcon *tcon;1246 struct cifs_tcon *tcon;
1169 struct tcon_link *tlink;1247 struct tcon_link *tlink;
1170 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1171 bool adjust_tz = false;
1172 struct cifs_fattr fattr = {0};
1173 bool symlink = false;
1174 struct cifs_open_info_data data = {};
1175 struct cifs_sid owner, group;1248 struct cifs_sid owner, group;
1176 int rc = 0;1249 int tmprc;
1177 int tmprc = 0;1250 int rc;
1178 1251
1179 tlink = cifs_sb_tlink(cifs_sb);1252 tlink = cifs_sb_tlink(cifs_sb);
1180 if (IS_ERR(tlink))1253 if (IS_ERR(tlink))
@@ -1185,14 +1258,9 @@ smb311_posix_get_inode_info(struct inode **inode, · 4 unmodified lines
1185 * 1. Fetch file metadata1258 * 1. Fetch file metadata
1186 */1259 */
1187 1260
1188 if (is_inode_cache_good(*inode)) {1261 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1189 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");1262 full_path, &data,
1190 goto out;1263 &owner, &group);
1191 }
1192
1193 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data,
1194 &owner, &group, &adjust_tz,
1195 &symlink);
1196 1264
1197 /*1265 /*
1198 * 2. Convert it to internal cifs metadata (fattr)1266 * 2. Convert it to internal cifs metadata (fattr)
@@ -1200,12 +1268,11 @@ smb311_posix_get_inode_info(struct inode **inode, · 1 unmodified line
1200 1268
1201 switch (rc) {1269 switch (rc) {
1202 case 0:1270 case 0:
1203 smb311_posix_info_to_fattr(&fattr, &data, &owner, &group,1271 smb311_posix_info_to_fattr(fattr, &data, &owner, &group, sb);
1204 sb, adjust_tz, symlink);
1205 break;1272 break;
1206 case -EREMOTE:1273 case -EREMOTE:
1207 /* DFS link, no metadata available on this server */1274 /* DFS link, no metadata available on this server */
1208 cifs_create_dfs_fattr(&fattr, sb);1275 cifs_create_junction_fattr(fattr, sb);
1209 rc = 0;1276 rc = 0;
1210 break;1277 break;
1211 case -EACCES:1278 case -EACCES:
@@ -1221,49 +1288,42 @@ smb311_posix_get_inode_info(struct inode **inode, · 9 unmodified lines
1221 goto out;1288 goto out;
1222 }1289 }
1223 1290
1224
1225 /*1291 /*
1226 * 3. Tweak fattr based on mount options1292 * 3. Tweak fattr based on mount options
1227 */1293 */
1228
1229 /* check for Minshall+French symlinks */1294 /* check for Minshall+French symlinks */
1230 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {1295 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1231 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,1296 tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
1232 full_path);1297 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1233 if (tmprc)
1234 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1235 }1298 }
1236 1299
1237 /*1300out:
1238 * 4. Update inode with final fattr data1301 cifs_put_tlink(tlink);
1239 */1302 cifs_free_open_info(&data);
1240 1303 return rc;
1241 if (!*inode) {1304}
1242 *inode = cifs_iget(sb, &fattr);
1243 if (!*inode)
1244 rc = -ENOMEM;
1245 } else {
1246 /* we already have inode, update it */
1247 1305
1248 /* if uniqueid is different, return error */1306int smb311_posix_get_inode_info(struct inode **inode, const char *full_path,
1249 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&1307 struct super_block *sb, const unsigned int xid)
1250 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {1308{
1251 CIFS_I(*inode)->time = 0; /* force reval */1309 struct cifs_fattr fattr = {};
1252 rc = -ESTALE;1310 int rc;
1253 goto out;
1254 }
1255 1311
1256 /* if filetype is different, return error */1312 if (is_inode_cache_good(*inode)) {
1257 rc = cifs_fattr_to_inode(*inode, &fattr);1313 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1314 return 0;
1258 }1315 }
1316
1317 rc = smb311_posix_get_fattr(&fattr, full_path, sb, xid);
1318 if (rc)
1319 goto out;
1320
1321 rc = update_inode_info(sb, &fattr, inode);
1259out:1322out:
1260 cifs_put_tlink(tlink);
1261 cifs_free_open_info(&data);
1262 kfree(fattr.cf_symlink_target);1323 kfree(fattr.cf_symlink_target);
1263 return rc;1324 return rc;
1264}1325}
1265 1326
1266
1267static const struct inode_operations cifs_ipc_inode_ops = {1327static const struct inode_operations cifs_ipc_inode_ops = {
1268 .lookup = cifs_lookup,1328 .lookup = cifs_lookup,
1269};1329};
@@ -1367,13 +1427,14 @@ retry_iget5_locked: · 97 unmodified lines
1367/* gets root inode */1427/* gets root inode */
1368struct inode *cifs_root_iget(struct super_block *sb)1428struct inode *cifs_root_iget(struct super_block *sb)
1369{1429{
1370 unsigned int xid;
1371 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);1430 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1372 struct inode *inode = NULL;1431 struct cifs_fattr fattr = {};
1373 long rc;
1374 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);1432 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
1433 struct inode *inode = NULL;
1434 unsigned int xid;
1375 char *path = NULL;1435 char *path = NULL;
1376 int len;1436 int len;
1437 int rc;
1377 1438
1378 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)1439 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1379 && cifs_sb->prepath) {1440 && cifs_sb->prepath) {
@@ -1391,21 +1452,29 @@ struct inode *cifs_root_iget(struct super_block *sb) · 11 unmodified lines
1391 1452
1392 xid = get_xid();1453 xid = get_xid();
1393 if (tcon->unix_ext) {1454 if (tcon->unix_ext) {
1394 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);1455 rc = cifs_get_unix_fattr(path, sb, &fattr, &inode, xid);
1395 /* some servers mistakenly claim POSIX support */1456 /* some servers mistakenly claim POSIX support */
1396 if (rc != -EOPNOTSUPP)1457 if (rc != -EOPNOTSUPP)
1397 goto iget_no_retry;1458 goto iget_root;
1398 cifs_dbg(VFS, "server does not support POSIX extensions\n");1459 cifs_dbg(VFS, "server does not support POSIX extensions\n");
1399 tcon->unix_ext = false;1460 tcon->unix_ext = false;
1400 }1461 }
1401 1462
1402 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));1463 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1403 if (tcon->posix_extensions)1464 if (tcon->posix_extensions)
1404 rc = smb311_posix_get_inode_info(&inode, path, sb, xid);1465 rc = smb311_posix_get_fattr(&fattr, path, sb, xid);
1405 else1466 else
1406 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);1467 rc = cifs_get_fattr(NULL, sb, xid, NULL, &fattr, &inode, path);
1468
1469iget_root:
1470 if (!rc) {
1471 if (fattr.cf_flags & CIFS_FATTR_JUNCTION) {
1472 fattr.cf_flags &= ~CIFS_FATTR_JUNCTION;
1473 cifs_autodisable_serverino(cifs_sb);
1474 }
1475 inode = cifs_iget(sb, &fattr);
1476 }
1407 1477
1408iget_no_retry:
1409 if (!inode) {1478 if (!inode) {
1410 inode = ERR_PTR(rc);1479 inode = ERR_PTR(rc);
1411 goto out;1480 goto out;
@@ -1429,6 +1498,7 @@ iget_no_retry: · 17 unmodified lines
1429out:1498out:
1430 kfree(path);1499 kfree(path);
1431 free_xid(xid);1500 free_xid(xid);
1501 kfree(fattr.cf_symlink_target);
1432 return inode;1502 return inode;
1433}1503}
1434 1504
fs/smb/client/misc.c+1−1
@@ -476,7 +476,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) · 475 unmodified lines
476 return false;476 return false;
477 477
478 /* If server is a channel, select the primary channel */478 /* If server is a channel, select the primary channel */
479 pserver = CIFS_SERVER_IS_CHAN(srv) ? srv->primary_server : srv;479 pserver = SERVER_IS_CHAN(srv) ? srv->primary_server : srv;
480 480
481 /* look up tcon based on tid & uid */481 /* look up tcon based on tid & uid */
482 spin_lock(&cifs_tcp_ses_lock);482 spin_lock(&cifs_tcp_ses_lock);
fs/smb/client/namespace.crenamed from fs/smb/client/cifs_dfs_ref.c+62−51
@@ -1,12 +1,12 @@
1// SPDX-License-Identifier: GPL-2.0-or-later1// SPDX-License-Identifier: GPL-2.0-or-later
2/*2/*
3 * Contains the CIFS DFS referral mounting routines used for handling3 * Contains mounting routines used for handling traversal via SMB junctions.
4 * traversal via DFS junction point
5 *4 *
6 * Copyright (c) 2007 Igor Mammedov5 * Copyright (c) 2007 Igor Mammedov
7 * Copyright (C) International Business Machines Corp., 20086 * Copyright (C) International Business Machines Corp., 2008
8 * Author(s): Igor Mammedov (niallain@gmail.com)7 * Author(s): Igor Mammedov (niallain@gmail.com)
9 * Steve French (sfrench@us.ibm.com)8 * Steve French (sfrench@us.ibm.com)
9 * Copyright (c) 2023 Paulo Alcantara <palcantara@suse.de>
10 */10 */
11 11
12#include <linux/dcache.h>12#include <linux/dcache.h>
@@ -19,32 +19,31 @@ · 6 unmodified lines
19#include "cifsglob.h"19#include "cifsglob.h"
20#include "cifsproto.h"20#include "cifsproto.h"
21#include "cifsfs.h"21#include "cifsfs.h"
22#include "dns_resolve.h"
23#include "cifs_debug.h"22#include "cifs_debug.h"
24#include "dfs.h"
25#include "fs_context.h"23#include "fs_context.h"
26 24
27static LIST_HEAD(cifs_dfs_automount_list);25static LIST_HEAD(cifs_automount_list);
28 26
29static void cifs_dfs_expire_automounts(struct work_struct *work);27static void cifs_expire_automounts(struct work_struct *work);
30static DECLARE_DELAYED_WORK(cifs_dfs_automount_task,28static DECLARE_DELAYED_WORK(cifs_automount_task,
31 cifs_dfs_expire_automounts);29 cifs_expire_automounts);
32static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ;30static int cifs_mountpoint_expiry_timeout = 500 * HZ;
33 31
34static void cifs_dfs_expire_automounts(struct work_struct *work)32static void cifs_expire_automounts(struct work_struct *work)
35{33{
36 struct list_head *list = &cifs_dfs_automount_list;34 struct list_head *list = &cifs_automount_list;
37 35
38 mark_mounts_for_expiry(list);36 mark_mounts_for_expiry(list);
39 if (!list_empty(list))37 if (!list_empty(list))
40 schedule_delayed_work(&cifs_dfs_automount_task,38 schedule_delayed_work(&cifs_automount_task,
41 cifs_dfs_mountpoint_expiry_timeout);39 cifs_mountpoint_expiry_timeout);
42}40}
43 41
44void cifs_dfs_release_automount_timer(void)42void cifs_release_automount_timer(void)
45{43{
46 BUG_ON(!list_empty(&cifs_dfs_automount_list));44 if (WARN_ON(!list_empty(&cifs_automount_list)))
47 cancel_delayed_work_sync(&cifs_dfs_automount_task);45 return;
46 cancel_delayed_work_sync(&cifs_automount_task);
48}47}
49 48
50/**49/**
@@ -118,26 +117,53 @@ cifs_build_devname(char *nodename, const char *prepath) · 67 unmodified lines
118 return dev;117 return dev;
119}118}
120 119
121static int set_dest_addr(struct smb3_fs_context *ctx)120/* Return full path out of a dentry set for automount */
121static char *automount_fullpath(struct dentry *dentry, void *page)
122{122{
123 struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;123 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
124 int rc;124 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
125 size_t len;
126 char *s;
127
128 spin_lock(&tcon->tc_lock);
129 if (!tcon->origin_fullpath) {
130 spin_unlock(&tcon->tc_lock);
131 return build_path_from_dentry_optional_prefix(dentry,
132 page,
133 true);
134 }
135 spin_unlock(&tcon->tc_lock);
136
137 s = dentry_path_raw(dentry, page, PATH_MAX);
138 if (IS_ERR(s))
139 return s;
140 /* for root, we want "" */
141 if (!s[1])
142 s++;
143
144 spin_lock(&tcon->tc_lock);
145 len = strlen(tcon->origin_fullpath);
146 if (s < (char *)page + len) {
147 spin_unlock(&tcon->tc_lock);
148 return ERR_PTR(-ENAMETOOLONG);
149 }
150
151 s -= len;
152 memcpy(s, tcon->origin_fullpath, len);
153 spin_unlock(&tcon->tc_lock);
154 convert_delimiter(s, '/');
125 155
126 rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL);156 return s;
127 if (!rc)
128 cifs_set_port(addr, ctx->port);
129 return rc;
130}157}
131 158
132/*159/*
133 * Create a vfsmount that we can automount160 * Create a vfsmount that we can automount
134 */161 */
135static struct vfsmount *cifs_dfs_do_automount(struct path *path)162static struct vfsmount *cifs_do_automount(struct path *path)
136{163{
137 int rc;164 int rc;
138 struct dentry *mntpt = path->dentry;165 struct dentry *mntpt = path->dentry;
139 struct fs_context *fc;166 struct fs_context *fc;
140 struct cifs_sb_info *cifs_sb;
141 void *page = NULL;167 void *page = NULL;
142 struct smb3_fs_context *ctx, *cur_ctx;168 struct smb3_fs_context *ctx, *cur_ctx;
143 struct smb3_fs_context tmp;169 struct smb3_fs_context tmp;
@@ -147,17 +173,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) · 3 unmodified lines
147 if (IS_ROOT(mntpt))173 if (IS_ROOT(mntpt))
148 return ERR_PTR(-ESTALE);174 return ERR_PTR(-ESTALE);
149 175
150 /*176 cur_ctx = CIFS_SB(mntpt->d_sb)->ctx;
151 * The MSDFS spec states that paths in DFS referral requests and
152 * responses must be prefixed by a single '\' character instead of
153 * the double backslashes usually used in the UNC. This function
154 * gives us the latter, so we must adjust the result.
155 */
156 cifs_sb = CIFS_SB(mntpt->d_sb);
157 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
158 return ERR_PTR(-EREMOTE);
159
160 cur_ctx = cifs_sb->ctx;
161 177
162 fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, mntpt);178 fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, mntpt);
163 if (IS_ERR(fc))179 if (IS_ERR(fc))
@@ -166,7 +182,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) · 2 unmodified lines
166 ctx = smb3_fc2context(fc);182 ctx = smb3_fc2context(fc);
167 183
168 page = alloc_dentry_path();184 page = alloc_dentry_path();
169 full_path = dfs_get_automount_devname(mntpt, page);185 full_path = automount_fullpath(mntpt, page);
170 if (IS_ERR(full_path)) {186 if (IS_ERR(full_path)) {
171 mnt = ERR_CAST(full_path);187 mnt = ERR_CAST(full_path);
172 goto out;188 goto out;
@@ -196,15 +212,10 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) · 23 unmodified lines
196 ctx->source = NULL;212 ctx->source = NULL;
197 goto out;213 goto out;
198 }214 }
199 cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dstaddr=%pISpc\n",215 cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s\n",
200 __func__, ctx->source, ctx->UNC, ctx->prepath, &ctx->dstaddr);216 __func__, ctx->source, ctx->UNC, ctx->prepath);
201
202 rc = set_dest_addr(ctx);
203 if (!rc)
204 mnt = fc_mount(fc);
205 else
206 mnt = ERR_PTR(rc);
207 217
218 mnt = fc_mount(fc);
208out:219out:
209 put_fs_context(fc);220 put_fs_context(fc);
210 free_dentry_path(page);221 free_dentry_path(page);
@@ -214,25 +225,25 @@ out: · 3 unmodified lines
214/*225/*
215 * Attempt to automount the referral226 * Attempt to automount the referral
216 */227 */
217struct vfsmount *cifs_dfs_d_automount(struct path *path)228struct vfsmount *cifs_d_automount(struct path *path)
218{229{
219 struct vfsmount *newmnt;230 struct vfsmount *newmnt;
220 231
221 cifs_dbg(FYI, "%s: %pd\n", __func__, path->dentry);232 cifs_dbg(FYI, "%s: %pd\n", __func__, path->dentry);
222 233
223 newmnt = cifs_dfs_do_automount(path);234 newmnt = cifs_do_automount(path);
224 if (IS_ERR(newmnt)) {235 if (IS_ERR(newmnt)) {
225 cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);236 cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
226 return newmnt;237 return newmnt;
227 }238 }
228 239
229 mntget(newmnt); /* prevent immediate expiration */240 mntget(newmnt); /* prevent immediate expiration */
230 mnt_set_expiry(newmnt, &cifs_dfs_automount_list);241 mnt_set_expiry(newmnt, &cifs_automount_list);
231 schedule_delayed_work(&cifs_dfs_automount_task,242 schedule_delayed_work(&cifs_automount_task,
232 cifs_dfs_mountpoint_expiry_timeout);243 cifs_mountpoint_expiry_timeout);
233 cifs_dbg(FYI, "leaving %s [ok]\n" , __func__);244 cifs_dbg(FYI, "leaving %s [ok]\n" , __func__);
234 return newmnt;245 return newmnt;
235}246}
236 247
237const struct inode_operations cifs_dfs_referral_inode_operations = {248const struct inode_operations cifs_namespace_inode_operations = {
238};249};
fs/smb/client/readdir.c+7−16
@@ -143,6 +143,7 @@ static bool reparse_file_needs_reval(const struct cifs_fattr *fattr) · 142 unmodified lines
143 case IO_REPARSE_TAG_DFSR:143 case IO_REPARSE_TAG_DFSR:
144 case IO_REPARSE_TAG_SYMLINK:144 case IO_REPARSE_TAG_SYMLINK:
145 case IO_REPARSE_TAG_NFS:145 case IO_REPARSE_TAG_NFS:
146 case IO_REPARSE_TAG_MOUNT_POINT:
146 case 0:147 case 0:
147 return true;148 return true;
148 }149 }
@@ -163,29 +164,19 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) · 14 unmodified lines
163 * TODO: go through all documented reparse tags to see if we can164 * TODO: go through all documented reparse tags to see if we can
164 * reasonably map some of them to directories vs. files vs. symlinks165 * reasonably map some of them to directories vs. files vs. symlinks
165 */166 */
167 if ((fattr->cf_cifsattrs & ATTR_REPARSE) &&
168 cifs_reparse_point_to_fattr(cifs_sb, fattr, fattr->cf_cifstag))
169 goto out_reparse;
170
166 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {171 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
167 fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;172 fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
168 fattr->cf_dtype = DT_DIR;173 fattr->cf_dtype = DT_DIR;
169 } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_SYMLINK) {174 } else {
170 fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
171 fattr->cf_dtype = DT_LNK;
172 } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_FIFO) {
173 fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
174 fattr->cf_dtype = DT_FIFO;
175 } else if (fattr->cf_cifstag == IO_REPARSE_TAG_AF_UNIX) {
176 fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
177 fattr->cf_dtype = DT_SOCK;
178 } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_CHR) {
179 fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
180 fattr->cf_dtype = DT_CHR;
181 } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_BLK) {
182 fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
183 fattr->cf_dtype = DT_BLK;
184 } else { /* TODO: should we mark some other reparse points (like DFSR) as directories? */
185 fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;175 fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;
186 fattr->cf_dtype = DT_REG;176 fattr->cf_dtype = DT_REG;
187 }177 }
188 178
179out_reparse:
189 /*180 /*
190 * We need to revalidate it further to make a decision about whether it181 * We need to revalidate it further to make a decision about whether it
191 * is a symbolic link, DFS referral or a reparse point with a direct182 * is a symbolic link, DFS referral or a reparse point with a direct
fs/smb/client/sess.c+43−29
@@ -323,12 +323,12 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) · 322 unmodified lines
323 ses->chans[chan_index].iface = iface;323 ses->chans[chan_index].iface = iface;
324 324
325 /* No iface is found. if secondary chan, drop connection */325 /* No iface is found. if secondary chan, drop connection */
326 if (!iface && CIFS_SERVER_IS_CHAN(server))326 if (!iface && SERVER_IS_CHAN(server))
327 ses->chans[chan_index].server = NULL;327 ses->chans[chan_index].server = NULL;
328 328
329 spin_unlock(&ses->chan_lock);329 spin_unlock(&ses->chan_lock);
330 330
331 if (!iface && CIFS_SERVER_IS_CHAN(server))331 if (!iface && SERVER_IS_CHAN(server))
332 cifs_put_tcp_session(server, false);332 cifs_put_tcp_session(server, false);
333 333
334 return rc;334 return rc;
@@ -360,11 +360,11 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, · 25 unmodified lines
360{360{
361 struct TCP_Server_Info *chan_server;361 struct TCP_Server_Info *chan_server;
362 struct cifs_chan *chan;362 struct cifs_chan *chan;
363 struct smb3_fs_context ctx = {NULL};363 struct smb3_fs_context *ctx;
364 static const char unc_fmt[] = "\\%s\\foo";364 static const char unc_fmt[] = "\\%s\\foo";
365 char unc[sizeof(unc_fmt)+SERVER_NAME_LEN_WITH_NULL] = {0};
366 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;365 struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
367 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;366 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
367 size_t len;
368 int rc;368 int rc;
369 unsigned int xid = get_xid();369 unsigned int xid = get_xid();
370 370
@@ -388,54 +388,64 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, · 17 unmodified lines
388 * the session and server without caring about memory388 * the session and server without caring about memory
389 * management.389 * management.
390 */390 */
391 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
392 if (!ctx) {
393 rc = -ENOMEM;
394 goto out_free_xid;
395 }
391 396
392 /* Always make new connection for now (TODO?) */397 /* Always make new connection for now (TODO?) */
393 ctx.nosharesock = true;398 ctx->nosharesock = true;
394 399
395 /* Auth */400 /* Auth */
396 ctx.domainauto = ses->domainAuto;401 ctx->domainauto = ses->domainAuto;
397 ctx.domainname = ses->domainName;402 ctx->domainname = ses->domainName;
398 403
399 /* no hostname for extra channels */404 /* no hostname for extra channels */
400 ctx.server_hostname = "";405 ctx->server_hostname = "";
401 406
402 ctx.username = ses->user_name;407 ctx->username = ses->user_name;
403 ctx.password = ses->password;408 ctx->password = ses->password;
404 ctx.sectype = ses->sectype;409 ctx->sectype = ses->sectype;
405 ctx.sign = ses->sign;410 ctx->sign = ses->sign;
406 411
407 /* UNC and paths */412 /* UNC and paths */
408 /* XXX: Use ses->server->hostname? */413 /* XXX: Use ses->server->hostname? */
409 sprintf(unc, unc_fmt, ses->ip_addr);414 len = sizeof(unc_fmt) + SERVER_NAME_LEN_WITH_NULL;
410 ctx.UNC = unc;415 ctx->UNC = kzalloc(len, GFP_KERNEL);
411 ctx.prepath = "";416 if (!ctx->UNC) {
417 rc = -ENOMEM;
418 goto out_free_ctx;
419 }
420 scnprintf(ctx->UNC, len, unc_fmt, ses->ip_addr);
421 ctx->prepath = "";
412 422
413 /* Reuse same version as master connection */423 /* Reuse same version as master connection */
414 ctx.vals = ses->server->vals;424 ctx->vals = ses->server->vals;
415 ctx.ops = ses->server->ops;425 ctx->ops = ses->server->ops;
416 426
417 ctx.noblocksnd = ses->server->noblocksnd;427 ctx->noblocksnd = ses->server->noblocksnd;
418 ctx.noautotune = ses->server->noautotune;428 ctx->noautotune = ses->server->noautotune;
419 ctx.sockopt_tcp_nodelay = ses->server->tcp_nodelay;429 ctx->sockopt_tcp_nodelay = ses->server->tcp_nodelay;
420 ctx.echo_interval = ses->server->echo_interval / HZ;430 ctx->echo_interval = ses->server->echo_interval / HZ;
421 ctx.max_credits = ses->server->max_credits;431 ctx->max_credits = ses->server->max_credits;
422 432
423 /*433 /*
424 * This will be used for encoding/decoding user/domain/pw434 * This will be used for encoding/decoding user/domain/pw
425 * during sess setup auth.435 * during sess setup auth.
426 */436 */
427 ctx.local_nls = cifs_sb->local_nls;437 ctx->local_nls = cifs_sb->local_nls;
428 438
429 /* Use RDMA if possible */439 /* Use RDMA if possible */
430 ctx.rdma = iface->rdma_capable;440 ctx->rdma = iface->rdma_capable;
431 memcpy(&ctx.dstaddr, &iface->sockaddr, sizeof(struct sockaddr_storage));441 memcpy(&ctx->dstaddr, &iface->sockaddr, sizeof(ctx->dstaddr));
432 442
433 /* reuse master con client guid */443 /* reuse master con client guid */
434 memcpy(&ctx.client_guid, ses->server->client_guid,444 memcpy(&ctx->client_guid, ses->server->client_guid,
435 SMB2_CLIENT_GUID_SIZE);445 sizeof(ctx->client_guid));
436 ctx.use_client_guid = true;446 ctx->use_client_guid = true;
437 447
438 chan_server = cifs_get_tcp_session(&ctx, ses->server);448 chan_server = cifs_get_tcp_session(ctx, ses->server);
439 449
440 spin_lock(&ses->chan_lock);450 spin_lock(&ses->chan_lock);
441 chan = &ses->chans[ses->chan_count];451 chan = &ses->chans[ses->chan_count];
@@ -497,6 +507,10 @@ out: · 55 unmodified lines
497 cifs_put_tcp_session(chan->server, 0);507 cifs_put_tcp_session(chan->server, 0);
498 }508 }
499 509
510 kfree(ctx->UNC);
511out_free_ctx:
512 kfree(ctx);
513out_free_xid:
500 free_xid(xid);514 free_xid(xid);
501 return rc;515 return rc;
502}516}
fs/smb/client/smb1ops.c+16−10
@@ -542,14 +542,17 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, · 541 unmodified lines
542 return rc;542 return rc;
543}543}
544 544
545static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,545static int cifs_query_path_info(const unsigned int xid,
546 struct cifs_sb_info *cifs_sb, const char *full_path,546 struct cifs_tcon *tcon,
547 struct cifs_open_info_data *data, bool *adjustTZ, bool *symlink)547 struct cifs_sb_info *cifs_sb,
548 const char *full_path,
549 struct cifs_open_info_data *data)
548{550{
549 int rc;551 int rc;
550 FILE_ALL_INFO fi = {};552 FILE_ALL_INFO fi = {};
551 553
552 *symlink = false;554 data->symlink = false;
555 data->adjust_tz = false;
553 556
554 /* could do find first instead but this returns more info */557 /* could do find first instead but this returns more info */
555 rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls,558 rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls,
@@ -562,7 +565,7 @@ static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, · 6 unmodified lines
562 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {565 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
563 rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls,566 rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls,
564 cifs_remap(cifs_sb));567 cifs_remap(cifs_sb));
565 *adjustTZ = true;568 data->adjust_tz = true;
566 }569 }
567 570
568 if (!rc) {571 if (!rc) {
@@ -589,7 +592,7 @@ static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, · 20 unmodified lines
589 /* Need to check if this is a symbolic link or not */592 /* Need to check if this is a symbolic link or not */
590 tmprc = CIFS_open(xid, &oparms, &oplock, NULL);593 tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
591 if (tmprc == -EOPNOTSUPP)594 if (tmprc == -EOPNOTSUPP)
592 *symlink = true;595 data->symlink = true;
593 else if (tmprc == 0)596 else if (tmprc == 0)
594 CIFSSMBClose(xid, tcon, fid.netfid);597 CIFSSMBClose(xid, tcon, fid.netfid);
595 }598 }
@@ -969,13 +972,16 @@ cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon, · 373 unmodified lines
969#endif972#endif
970}973}
971 974
972static int975static int cifs_query_symlink(const unsigned int xid,
973cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,976 struct cifs_tcon *tcon,
974 struct cifs_sb_info *cifs_sb, const char *full_path,977 struct cifs_sb_info *cifs_sb,
975 char **target_path, bool is_reparse_point)978 const char *full_path,
979 char **target_path,
980 struct kvec *rsp_iov)
976{981{
977 int rc;982 int rc;
978 int oplock = 0;983 int oplock = 0;
984 bool is_reparse_point = !!rsp_iov;
979 struct cifs_fid fid;985 struct cifs_fid fid;
980 struct cifs_open_parms oparms;986 struct cifs_open_parms oparms;
981 987
fs/smb/client/smb2inode.c+115−88
@@ -35,34 +35,22 @@ free_set_inf_compound(struct smb_rqst *rqst) · 34 unmodified lines
35 SMB2_close_free(&rqst[2]);35 SMB2_close_free(&rqst[2]);
36}36}
37 37
38
39struct cop_vars {
40 struct cifs_open_parms oparms;
41 struct kvec rsp_iov[3];
42 struct smb_rqst rqst[3];
43 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
44 struct kvec qi_iov[1];
45 struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
46 struct kvec close_iov[1];
47 struct smb2_file_rename_info rename_info;
48 struct smb2_file_link_info link_info;
49};
50
51/*38/*
52 * note: If cfile is passed, the reference to it is dropped here.39 * note: If cfile is passed, the reference to it is dropped here.
53 * So make sure that you do not reuse cfile after return from this func.40 * So make sure that you do not reuse cfile after return from this func.
54 *41 *
55 * If passing @err_iov and @err_buftype, ensure to make them both large enough (>= 3) to hold all42 * If passing @out_iov and @out_buftype, ensure to make them both large enough
56 * error responses. Caller is also responsible for freeing them up.43 * (>= 3) to hold all compounded responses. Caller is also responsible for
44 * freeing them up with free_rsp_buf().
57 */45 */
58static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,46static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
59 struct cifs_sb_info *cifs_sb, const char *full_path,47 struct cifs_sb_info *cifs_sb, const char *full_path,
60 __u32 desired_access, __u32 create_disposition, __u32 create_options,48 __u32 desired_access, __u32 create_disposition, __u32 create_options,
61 umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile,49 umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile,
62 __u8 **extbuf, size_t *extbuflen,50 __u8 **extbuf, size_t *extbuflen,
63 struct kvec *err_iov, int *err_buftype)51 struct kvec *out_iov, int *out_buftype)
64{52{
65 struct cop_vars *vars = NULL;53 struct smb2_compound_vars *vars = NULL;
66 struct kvec *rsp_iov;54 struct kvec *rsp_iov;
67 struct smb_rqst *rqst;55 struct smb_rqst *rqst;
68 int rc;56 int rc;
@@ -133,7 +121,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, · 64 unmodified lines
133 /* Operation */121 /* Operation */
134 switch (command) {122 switch (command) {
135 case SMB2_OP_QUERY_INFO:123 case SMB2_OP_QUERY_INFO:
136 rqst[num_rqst].rq_iov = &vars->qi_iov[0];124 rqst[num_rqst].rq_iov = &vars->qi_iov;
137 rqst[num_rqst].rq_nvec = 1;125 rqst[num_rqst].rq_nvec = 1;
138 126
139 if (cfile)127 if (cfile)
@@ -167,7 +155,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, · 27 unmodified lines
167 full_path);155 full_path);
168 break;156 break;
169 case SMB2_OP_POSIX_QUERY_INFO:157 case SMB2_OP_POSIX_QUERY_INFO:
170 rqst[num_rqst].rq_iov = &vars->qi_iov[0];158 rqst[num_rqst].rq_iov = &vars->qi_iov;
171 rqst[num_rqst].rq_nvec = 1;159 rqst[num_rqst].rq_nvec = 1;
172 160
173 if (cfile)161 if (cfile)
@@ -375,7 +363,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, · 201 unmodified lines
375 goto after_close;363 goto after_close;
376 /* Close */364 /* Close */
377 flags |= CIFS_CP_CREATE_CLOSE_OP;365 flags |= CIFS_CP_CREATE_CLOSE_OP;
378 rqst[num_rqst].rq_iov = &vars->close_iov[0];366 rqst[num_rqst].rq_iov = &vars->close_iov;
379 rqst[num_rqst].rq_nvec = 1;367 rqst[num_rqst].rq_nvec = 1;
380 rc = SMB2_close_init(tcon, server,368 rc = SMB2_close_init(tcon, server,
381 &rqst[num_rqst], COMPOUND_FID,369 &rqst[num_rqst], COMPOUND_FID,
@@ -529,9 +517,9 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, · 147 unmodified lines
529 if (cfile)517 if (cfile)
530 cifsFileInfo_put(cfile);518 cifsFileInfo_put(cfile);
531 519
532 if (rc && err_iov && err_buftype) {520 if (out_iov && out_buftype) {
533 memcpy(err_iov, rsp_iov, 3 * sizeof(*err_iov));521 memcpy(out_iov, rsp_iov, 3 * sizeof(*out_iov));
534 memcpy(err_buftype, resp_buftype, 3 * sizeof(*err_buftype));522 memcpy(out_buftype, resp_buftype, 3 * sizeof(*out_buftype));
535 } else {523 } else {
536 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);524 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
537 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);525 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
@@ -541,20 +529,50 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, · 3 unmodified lines
541 return rc;529 return rc;
542}530}
543 531
544int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,532static int parse_create_response(struct cifs_open_info_data *data,
545 struct cifs_sb_info *cifs_sb, const char *full_path,533 struct cifs_sb_info *cifs_sb,
546 struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)534 const struct kvec *iov)
535{
536 struct smb2_create_rsp *rsp = iov->iov_base;
537 bool reparse_point = false;
538 u32 tag = 0;
539 int rc = 0;
540
541 switch (rsp->hdr.Status) {
542 case STATUS_STOPPED_ON_SYMLINK:
543 rc = smb2_parse_symlink_response(cifs_sb, iov,
544 &data->symlink_target);
545 if (rc)
546 return rc;
547 tag = IO_REPARSE_TAG_SYMLINK;
548 reparse_point = true;
549 break;
550 case STATUS_SUCCESS:
551 reparse_point = !!(rsp->Flags & SMB2_CREATE_FLAG_REPARSEPOINT);
552 break;
553 }
554 data->reparse_point = reparse_point;
555 data->reparse_tag = tag;
556 return rc;
557}
558
559int smb2_query_path_info(const unsigned int xid,
560 struct cifs_tcon *tcon,
561 struct cifs_sb_info *cifs_sb,
562 const char *full_path,
563 struct cifs_open_info_data *data)
547{564{
548 __u32 create_options = 0;565 __u32 create_options = 0;
549 struct cifsFileInfo *cfile;566 struct cifsFileInfo *cfile;
550 struct cached_fid *cfid = NULL;567 struct cached_fid *cfid = NULL;
551 struct kvec err_iov[3] = {};568 struct smb2_hdr *hdr;
552 int err_buftype[3] = {};569 struct kvec out_iov[3] = {};
570 int out_buftype[3] = {};
553 bool islink;571 bool islink;
554 int rc, rc2;572 int rc, rc2;
555 573
556 *adjust_tz = false;574 data->adjust_tz = false;
557 *reparse = false;575 data->reparse_point = false;
558 576
559 if (strcmp(full_path, ""))577 if (strcmp(full_path, ""))
560 rc = -ENOENT;578 rc = -ENOENT;
@@ -575,69 +593,73 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, · 14 unmodified lines
575 cifs_get_readable_path(tcon, full_path, &cfile);593 cifs_get_readable_path(tcon, full_path, &cfile);
576 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,594 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
577 create_options, ACL_NO_MODE, data, SMB2_OP_QUERY_INFO, cfile,595 create_options, ACL_NO_MODE, data, SMB2_OP_QUERY_INFO, cfile,
578 NULL, NULL, err_iov, err_buftype);596 NULL, NULL, out_iov, out_buftype);
579 if (rc) {597 hdr = out_iov[0].iov_base;
580 struct smb2_hdr *hdr = err_iov[0].iov_base;598 /*
581 599 * If first iov is unset, then SMB session was dropped or we've got a
582 if (unlikely(!hdr || err_buftype[0] == CIFS_NO_BUFFER))600 * cached open file (@cfile).
601 */
602 if (!hdr || out_buftype[0] == CIFS_NO_BUFFER)
603 goto out;
604
605 switch (rc) {
606 case 0:
607 case -EOPNOTSUPP:
608 rc = parse_create_response(data, cifs_sb, &out_iov[0]);
609 if (rc || !data->reparse_point)
583 goto out;610 goto out;
584 if (rc == -EOPNOTSUPP && hdr->Command == SMB2_CREATE &&611
585 hdr->Status == STATUS_STOPPED_ON_SYMLINK) {612 create_options |= OPEN_REPARSE_POINT;
586 rc = smb2_parse_symlink_response(cifs_sb, err_iov,613 /* Failed on a symbolic link - query a reparse point info */
587 &data->symlink_target);614 cifs_get_readable_path(tcon, full_path, &cfile);
588 if (rc)615 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
589 goto out;616 FILE_READ_ATTRIBUTES, FILE_OPEN,
590 617 create_options, ACL_NO_MODE, data,
591 *reparse = true;618 SMB2_OP_QUERY_INFO, cfile, NULL, NULL,
592 create_options |= OPEN_REPARSE_POINT;619 NULL, NULL);
593 620 break;
594 /* Failed on a symbolic link - query a reparse point info */621 case -EREMOTE:
595 cifs_get_readable_path(tcon, full_path, &cfile);622 break;
596 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,623 default:
597 FILE_READ_ATTRIBUTES, FILE_OPEN,624 if (hdr->Status != STATUS_OBJECT_NAME_INVALID)
598 create_options, ACL_NO_MODE, data,625 break;
599 SMB2_OP_QUERY_INFO, cfile, NULL, NULL,626 rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
600 NULL, NULL);627 full_path, &islink);
628 if (rc2) {
629 rc = rc2;
601 goto out;630 goto out;
602 } else if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) {
603 rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
604 full_path, &islink);
605 if (rc2) {
606 rc = rc2;
607 goto out;
608 }
609 if (islink)
610 rc = -EREMOTE;
611 }631 }
632 if (islink)
633 rc = -EREMOTE;
612 }634 }
613 635
614out:636out:
615 free_rsp_buf(err_buftype[0], err_iov[0].iov_base);637 free_rsp_buf(out_buftype[0], out_iov[0].iov_base);
616 free_rsp_buf(err_buftype[1], err_iov[1].iov_base);638 free_rsp_buf(out_buftype[1], out_iov[1].iov_base);
617 free_rsp_buf(err_buftype[2], err_iov[2].iov_base);639 free_rsp_buf(out_buftype[2], out_iov[2].iov_base);
618 return rc;640 return rc;
619}641}
620 642
621 643int smb311_posix_query_path_info(const unsigned int xid,
622int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,644 struct cifs_tcon *tcon,
623 struct cifs_sb_info *cifs_sb, const char *full_path,645 struct cifs_sb_info *cifs_sb,
646 const char *full_path,
624 struct cifs_open_info_data *data,647 struct cifs_open_info_data *data,
625 struct cifs_sid *owner,648 struct cifs_sid *owner,
626 struct cifs_sid *group,649 struct cifs_sid *group)
627 bool *adjust_tz, bool *reparse)
628{650{
629 int rc;651 int rc;
630 __u32 create_options = 0;652 __u32 create_options = 0;
631 struct cifsFileInfo *cfile;653 struct cifsFileInfo *cfile;
632 struct kvec err_iov[3] = {};654 struct kvec out_iov[3] = {};
633 int err_buftype[3] = {};655 int out_buftype[3] = {};
634 __u8 *sidsbuf = NULL;656 __u8 *sidsbuf = NULL;
635 __u8 *sidsbuf_end = NULL;657 __u8 *sidsbuf_end = NULL;
636 size_t sidsbuflen = 0;658 size_t sidsbuflen = 0;
637 size_t owner_len, group_len;659 size_t owner_len, group_len;
638 660
639 *adjust_tz = false;661 data->adjust_tz = false;
640 *reparse = false;662 data->reparse_point = false;
641 663
642 /*664 /*
643 * BB TODO: Add support for using the cached root handle.665 * BB TODO: Add support for using the cached root handle.
@@ -649,27 +671,33 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, · 5 unmodified lines
649 cifs_get_readable_path(tcon, full_path, &cfile);671 cifs_get_readable_path(tcon, full_path, &cfile);
650 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,672 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
651 create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,673 create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,
652 &sidsbuf, &sidsbuflen, err_iov, err_buftype);674 &sidsbuf, &sidsbuflen, out_iov, out_buftype);
653 if (rc == -EOPNOTSUPP) {675 /*
676 * If first iov is unset, then SMB session was dropped or we've got a
677 * cached open file (@cfile).
678 */
679 if (!out_iov[0].iov_base || out_buftype[0] == CIFS_NO_BUFFER)
680 goto out;
681
682 switch (rc) {
683 case 0:
684 case -EOPNOTSUPP:
654 /* BB TODO: When support for special files added to Samba re-verify this path */685 /* BB TODO: When support for special files added to Samba re-verify this path */
655 if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&686 rc = parse_create_response(data, cifs_sb, &out_iov[0]);
656 ((struct smb2_hdr *)err_iov[0].iov_base)->Command == SMB2_CREATE &&687 if (rc || !data->reparse_point)
657 ((struct smb2_hdr *)err_iov[0].iov_base)->Status == STATUS_STOPPED_ON_SYMLINK) {688 goto out;
658 rc = smb2_parse_symlink_response(cifs_sb, err_iov, &data->symlink_target);
659 if (rc)
660 goto out;
661 }
662 *reparse = true;
663 create_options |= OPEN_REPARSE_POINT;
664 689
690 create_options |= OPEN_REPARSE_POINT;
665 /* Failed on a symbolic link - query a reparse point info */691 /* Failed on a symbolic link - query a reparse point info */
666 cifs_get_readable_path(tcon, full_path, &cfile);692 cifs_get_readable_path(tcon, full_path, &cfile);
667 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,693 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
668 FILE_OPEN, create_options, ACL_NO_MODE, data,694 FILE_OPEN, create_options, ACL_NO_MODE, data,
669 SMB2_OP_POSIX_QUERY_INFO, cfile,695 SMB2_OP_POSIX_QUERY_INFO, cfile,
670 &sidsbuf, &sidsbuflen, NULL, NULL);696 &sidsbuf, &sidsbuflen, NULL, NULL);
697 break;
671 }698 }
672 699
700out:
673 if (rc == 0) {701 if (rc == 0) {
674 sidsbuf_end = sidsbuf + sidsbuflen;702 sidsbuf_end = sidsbuf + sidsbuflen;
675 703
@@ -689,11 +717,10 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, · 13 unmodified lines
689 memcpy(group, sidsbuf + owner_len, group_len);717 memcpy(group, sidsbuf + owner_len, group_len);
690 }718 }
691 719
692out:
693 kfree(sidsbuf);720 kfree(sidsbuf);
694 free_rsp_buf(err_buftype[0], err_iov[0].iov_base);721 free_rsp_buf(out_buftype[0], out_iov[0].iov_base);
695 free_rsp_buf(err_buftype[1], err_iov[1].iov_base);722 free_rsp_buf(out_buftype[1], out_iov[1].iov_base);
696 free_rsp_buf(err_buftype[2], err_iov[2].iov_base);723 free_rsp_buf(out_buftype[2], out_iov[2].iov_base);
697 return rc;724 return rc;
698}725}
699 726
fs/smb/client/smb2misc.c+3−3
@@ -145,7 +145,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server) · 144 unmodified lines
145 __u64 mid;145 __u64 mid;
146 146
147 /* If server is a channel, select the primary channel */147 /* If server is a channel, select the primary channel */
148 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;148 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
149 149
150 /*150 /*
151 * Add function to do table lookup of StructureSize by command151 * Add function to do table lookup of StructureSize by command
@@ -623,7 +623,7 @@ smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server) · 471 unmodified lines
623 cifs_dbg(FYI, "Checking for lease break\n");623 cifs_dbg(FYI, "Checking for lease break\n");
624 624
625 /* If server is a channel, select the primary channel */625 /* If server is a channel, select the primary channel */
626 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;626 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
627 627
628 /* look up tcon based on tid & uid */628 /* look up tcon based on tid & uid */
629 spin_lock(&cifs_tcp_ses_lock);629 spin_lock(&cifs_tcp_ses_lock);
@@ -698,7 +698,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) · 68 unmodified lines
698 cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel);698 cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel);
699 699
700 /* If server is a channel, select the primary channel */700 /* If server is a channel, select the primary channel */
701 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;701 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
702 702
703 /* look up tcon based on tid & uid */703 /* look up tcon based on tid & uid */
704 spin_lock(&cifs_tcp_ses_lock);704 spin_lock(&cifs_tcp_ses_lock);
fs/smb/client/smb2ops.c+91−207
@@ -172,8 +172,17 @@ smb2_set_credits(struct TCP_Server_Info *server, const int val) · 171 unmodified lines
172 172
173 spin_lock(&server->req_lock);173 spin_lock(&server->req_lock);
174 server->credits = val;174 server->credits = val;
175 if (val == 1)175 if (val == 1) {
176 server->reconnect_instance++;176 server->reconnect_instance++;
177 /*
178 * ChannelSequence updated for all channels in primary channel so that consistent
179 * across SMB3 requests sent on any channel. See MS-SMB2 3.2.4.1 and 3.2.7.1
180 */
181 if (SERVER_IS_CHAN(server))
182 server->primary_server->channel_sequence_num++;
183 else
184 server->channel_sequence_num++;
185 }
177 scredits = server->credits;186 scredits = server->credits;
178 in_flight = server->in_flight;187 in_flight = server->in_flight;
179 spin_unlock(&server->req_lock);188 spin_unlock(&server->req_lock);
@@ -1075,31 +1084,28 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, · 895 unmodified lines
1075 return rc;1084 return rc;
1076}1085}
1077 1086
1078
1079static int1087static int
1080smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,1088smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
1081 const char *path, const char *ea_name, const void *ea_value,1089 const char *path, const char *ea_name, const void *ea_value,
1082 const __u16 ea_value_len, const struct nls_table *nls_codepage,1090 const __u16 ea_value_len, const struct nls_table *nls_codepage,
1083 struct cifs_sb_info *cifs_sb)1091 struct cifs_sb_info *cifs_sb)
1084{1092{
1093 struct smb2_compound_vars *vars;
1085 struct cifs_ses *ses = tcon->ses;1094 struct cifs_ses *ses = tcon->ses;
1086 struct TCP_Server_Info *server = cifs_pick_channel(ses);1095 struct TCP_Server_Info *server = cifs_pick_channel(ses);
1096 struct smb_rqst *rqst;
1097 struct kvec *rsp_iov;
1087 __le16 *utf16_path = NULL;1098 __le16 *utf16_path = NULL;
1088 int ea_name_len = strlen(ea_name);1099 int ea_name_len = strlen(ea_name);
1089 int flags = CIFS_CP_CREATE_CLOSE_OP;1100 int flags = CIFS_CP_CREATE_CLOSE_OP;
1090 int len;1101 int len;
1091 struct smb_rqst rqst[3];
1092 int resp_buftype[3];1102 int resp_buftype[3];
1093 struct kvec rsp_iov[3];
1094 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
1095 struct cifs_open_parms oparms;1103 struct cifs_open_parms oparms;
1096 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;1104 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
1097 struct cifs_fid fid;1105 struct cifs_fid fid;
1098 struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
1099 unsigned int size[1];1106 unsigned int size[1];
1100 void *data[1];1107 void *data[1];
1101 struct smb2_file_full_ea_info *ea = NULL;1108 struct smb2_file_full_ea_info *ea = NULL;
1102 struct kvec close_iov[1];
1103 struct smb2_query_info_rsp *rsp;1109 struct smb2_query_info_rsp *rsp;
1104 int rc, used_len = 0;1110 int rc, used_len = 0;
1105 1111
@@ -1113,9 +1119,14 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, · 7 unmodified lines
1113 if (!utf16_path)1119 if (!utf16_path)
1114 return -ENOMEM;1120 return -ENOMEM;
1115 1121
1116 memset(rqst, 0, sizeof(rqst));
1117 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;1122 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
1118 memset(rsp_iov, 0, sizeof(rsp_iov));1123 vars = kzalloc(sizeof(*vars), GFP_KERNEL);
1124 if (!vars) {
1125 rc = -ENOMEM;
1126 goto out_free_path;
1127 }
1128 rqst = vars->rqst;
1129 rsp_iov = vars->rsp_iov;
1119 1130
1120 if (ses->server->ops->query_all_EAs) {1131 if (ses->server->ops->query_all_EAs) {
1121 if (!ea_value) {1132 if (!ea_value) {
@@ -1160,8 +1171,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, · 38 unmodified lines
1160 }1171 }
1161 1172
1162 /* Open */1173 /* Open */
1163 memset(&open_iov, 0, sizeof(open_iov));1174 rqst[0].rq_iov = vars->open_iov;
1164 rqst[0].rq_iov = open_iov;
1165 rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;1175 rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
1166 1176
1167 oparms = (struct cifs_open_parms) {1177 oparms = (struct cifs_open_parms) {
@@ -1181,8 +1191,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, · 13 unmodified lines
1181 1191
1182 1192
1183 /* Set Info */1193 /* Set Info */
1184 memset(&si_iov, 0, sizeof(si_iov));1194 rqst[1].rq_iov = vars->si_iov;
1185 rqst[1].rq_iov = si_iov;
1186 rqst[1].rq_nvec = 1;1195 rqst[1].rq_nvec = 1;
1187 1196
1188 len = sizeof(*ea) + ea_name_len + ea_value_len + 1;1197 len = sizeof(*ea) + ea_name_len + ea_value_len + 1;
@@ -1210,10 +1219,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, · 21 unmodified lines
1210 smb2_set_next_command(tcon, &rqst[1]);1219 smb2_set_next_command(tcon, &rqst[1]);
1211 smb2_set_related(&rqst[1]);1220 smb2_set_related(&rqst[1]);
1212 1221
1213
1214 /* Close */1222 /* Close */
1215 memset(&close_iov, 0, sizeof(close_iov));1223 rqst[2].rq_iov = &vars->close_iov;
1216 rqst[2].rq_iov = close_iov;
1217 rqst[2].rq_nvec = 1;1224 rqst[2].rq_nvec = 1;
1218 rc = SMB2_close_init(tcon, server,1225 rc = SMB2_close_init(tcon, server,
1219 &rqst[2], COMPOUND_FID, COMPOUND_FID, false);1226 &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
@@ -1228,13 +1235,15 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, · 8 unmodified lines
1228 1235
1229 sea_exit:1236 sea_exit:
1230 kfree(ea);1237 kfree(ea);
1231 kfree(utf16_path);
1232 SMB2_open_free(&rqst[0]);1238 SMB2_open_free(&rqst[0]);
1233 SMB2_set_info_free(&rqst[1]);1239 SMB2_set_info_free(&rqst[1]);
1234 SMB2_close_free(&rqst[2]);1240 SMB2_close_free(&rqst[2]);
1235 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);1241 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
1236 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);1242 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
1237 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);1243 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
1244 kfree(vars);
1245out_free_path:
1246 kfree(utf16_path);
1238 return rc;1247 return rc;
1239}1248}
1240#endif1249#endif
@@ -1446,16 +1455,6 @@ req_res_key_exit: · 205 unmodified lines
1446 return rc;1455 return rc;
1447}1456}
1448 1457
1449struct iqi_vars {
1450 struct smb_rqst rqst[3];
1451 struct kvec rsp_iov[3];
1452 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
1453 struct kvec qi_iov[1];
1454 struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
1455 struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
1456 struct kvec close_iov[1];
1457};
1458
1459static int1458static int
1460smb2_ioctl_query_info(const unsigned int xid,1459smb2_ioctl_query_info(const unsigned int xid,
1461 struct cifs_tcon *tcon,1460 struct cifs_tcon *tcon,
@@ -1463,7 +1462,7 @@ smb2_ioctl_query_info(const unsigned int xid, · 1 unmodified line
1463 __le16 *path, int is_dir,1462 __le16 *path, int is_dir,
1464 unsigned long p)1463 unsigned long p)
1465{1464{
1466 struct iqi_vars *vars;1465 struct smb2_compound_vars *vars;
1467 struct smb_rqst *rqst;1466 struct smb_rqst *rqst;
1468 struct kvec *rsp_iov;1467 struct kvec *rsp_iov;
1469 struct cifs_ses *ses = tcon->ses;1468 struct cifs_ses *ses = tcon->ses;
@@ -1581,7 +1580,7 @@ smb2_ioctl_query_info(const unsigned int xid, · 111 unmodified lines
1581 rc = -EINVAL;1580 rc = -EINVAL;
1582 goto free_open_req;1581 goto free_open_req;
1583 }1582 }
1584 rqst[1].rq_iov = &vars->si_iov[0];1583 rqst[1].rq_iov = vars->si_iov;
1585 rqst[1].rq_nvec = 1;1584 rqst[1].rq_nvec = 1;
1586 1585
1587 /* MS-FSCC 2.4.13 FileEndOfFileInformation */1586 /* MS-FSCC 2.4.13 FileEndOfFileInformation */
@@ -1593,7 +1592,7 @@ smb2_ioctl_query_info(const unsigned int xid, · 5 unmodified lines
1593 SMB2_O_INFO_FILE, 0, data, size);1592 SMB2_O_INFO_FILE, 0, data, size);
1594 free_req1_func = SMB2_set_info_free;1593 free_req1_func = SMB2_set_info_free;
1595 } else if (qi.flags == PASSTHRU_QUERY_INFO) {1594 } else if (qi.flags == PASSTHRU_QUERY_INFO) {
1596 rqst[1].rq_iov = &vars->qi_iov[0];1595 rqst[1].rq_iov = &vars->qi_iov;
1597 rqst[1].rq_nvec = 1;1596 rqst[1].rq_nvec = 1;
1598 1597
1599 rc = SMB2_query_info_init(tcon, server,1598 rc = SMB2_query_info_init(tcon, server,
@@ -1615,7 +1614,7 @@ smb2_ioctl_query_info(const unsigned int xid, · 15 unmodified lines
1615 smb2_set_related(&rqst[1]);1614 smb2_set_related(&rqst[1]);
1616 1615
1617 /* Close */1616 /* Close */
1618 rqst[2].rq_iov = &vars->close_iov[0];1617 rqst[2].rq_iov = &vars->close_iov;
1619 rqst[2].rq_nvec = 1;1618 rqst[2].rq_nvec = 1;
1620 1619
1621 rc = SMB2_close_init(tcon, server,1620 rc = SMB2_close_init(tcon, server,
@@ -2408,7 +2407,7 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) · 786 unmodified lines
2408 return false;2407 return false;
2409 2408
2410 /* If server is a channel, select the primary channel */2409 /* If server is a channel, select the primary channel */
2411 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;2410 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
2412 2411
2413 spin_lock(&cifs_tcp_ses_lock);2412 spin_lock(&cifs_tcp_ses_lock);
2414 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {2413 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
@@ -2524,15 +2523,13 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, · 109 unmodified lines
2524 struct kvec *rsp, int *buftype,2523 struct kvec *rsp, int *buftype,
2525 struct cifs_sb_info *cifs_sb)2524 struct cifs_sb_info *cifs_sb)
2526{2525{
2526 struct smb2_compound_vars *vars;
2527 struct cifs_ses *ses = tcon->ses;2527 struct cifs_ses *ses = tcon->ses;
2528 struct TCP_Server_Info *server = cifs_pick_channel(ses);2528 struct TCP_Server_Info *server = cifs_pick_channel(ses);
2529 int flags = CIFS_CP_CREATE_CLOSE_OP;2529 int flags = CIFS_CP_CREATE_CLOSE_OP;
2530 struct smb_rqst rqst[3];2530 struct smb_rqst *rqst;
2531 int resp_buftype[3];2531 int resp_buftype[3];
2532 struct kvec rsp_iov[3];2532 struct kvec *rsp_iov;
2533 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
2534 struct kvec qi_iov[1];
2535 struct kvec close_iov[1];
2536 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;2533 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
2537 struct cifs_open_parms oparms;2534 struct cifs_open_parms oparms;
2538 struct cifs_fid fid;2535 struct cifs_fid fid;
@@ -2549,9 +2546,14 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, · 10 unmodified lines
2549 if (smb3_encryption_required(tcon))2546 if (smb3_encryption_required(tcon))
2550 flags |= CIFS_TRANSFORM_REQ;2547 flags |= CIFS_TRANSFORM_REQ;
2551 2548
2552 memset(rqst, 0, sizeof(rqst));
2553 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;2549 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
2554 memset(rsp_iov, 0, sizeof(rsp_iov));2550 vars = kzalloc(sizeof(*vars), GFP_KERNEL);
2551 if (!vars) {
2552 rc = -ENOMEM;
2553 goto out_free_path;
2554 }
2555 rqst = vars->rqst;
2556 rsp_iov = vars->rsp_iov;
2555 2557
2556 /*2558 /*
2557 * We can only call this for things we know are directories.2559 * We can only call this for things we know are directories.
@@ -2560,8 +2562,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, · 2 unmodified lines
2560 open_cached_dir(xid, tcon, path, cifs_sb, false,2562 open_cached_dir(xid, tcon, path, cifs_sb, false,
2561 &cfid); /* cfid null if open dir failed */2563 &cfid); /* cfid null if open dir failed */
2562 2564
2563 memset(&open_iov, 0, sizeof(open_iov));2565 rqst[0].rq_iov = vars->open_iov;
2564 rqst[0].rq_iov = open_iov;
2565 rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;2566 rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
2566 2567
2567 oparms = (struct cifs_open_parms) {2568 oparms = (struct cifs_open_parms) {
@@ -2579,8 +2580,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, · 11 unmodified lines
2579 goto qic_exit;2580 goto qic_exit;
2580 smb2_set_next_command(tcon, &rqst[0]);2581 smb2_set_next_command(tcon, &rqst[0]);
2581 2582
2582 memset(&qi_iov, 0, sizeof(qi_iov));2583 rqst[1].rq_iov = &vars->qi_iov;
2583 rqst[1].rq_iov = qi_iov;
2584 rqst[1].rq_nvec = 1;2584 rqst[1].rq_nvec = 1;
2585 2585
2586 if (cfid) {2586 if (cfid) {
@@ -2607,8 +2607,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, · 20 unmodified lines
2607 smb2_set_related(&rqst[1]);2607 smb2_set_related(&rqst[1]);
2608 }2608 }
2609 2609
2610 memset(&close_iov, 0, sizeof(close_iov));2610 rqst[2].rq_iov = &vars->close_iov;
2611 rqst[2].rq_iov = close_iov;
2612 rqst[2].rq_nvec = 1;2611 rqst[2].rq_nvec = 1;
2613 2612
2614 rc = SMB2_close_init(tcon, server,2613 rc = SMB2_close_init(tcon, server,
@@ -2639,7 +2638,6 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, · 24 unmodified lines
2639 *buftype = resp_buftype[1];2638 *buftype = resp_buftype[1];
2640 2639
2641 qic_exit:2640 qic_exit:
2642 kfree(utf16_path);
2643 SMB2_open_free(&rqst[0]);2641 SMB2_open_free(&rqst[0]);
2644 SMB2_query_info_free(&rqst[1]);2642 SMB2_query_info_free(&rqst[1]);
2645 SMB2_close_free(&rqst[2]);2643 SMB2_close_free(&rqst[2]);
@@ -2647,6 +2645,9 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, · 1 unmodified line
2647 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);2645 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
2648 if (cfid)2646 if (cfid)
2649 close_cached_dir(cfid);2647 close_cached_dir(cfid);
2648 kfree(vars);
2649out_free_path:
2650 kfree(utf16_path);
2650 return rc;2651 return rc;
2651}2652}
2652 2653
@@ -2949,154 +2950,32 @@ parse_reparse_point(struct reparse_data_buffer *buf, · 296 unmodified lines
2949 }2950 }
2950}2951}
2951 2952
2952static int2953static int smb2_query_symlink(const unsigned int xid,
2953smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,2954 struct cifs_tcon *tcon,
2954 struct cifs_sb_info *cifs_sb, const char *full_path,2955 struct cifs_sb_info *cifs_sb,
2955 char **target_path, bool is_reparse_point)2956 const char *full_path,
2957 char **target_path,
2958 struct kvec *rsp_iov)
2956{2959{
2957 int rc;2960 struct reparse_data_buffer *buf;
2958 __le16 *utf16_path = NULL;2961 struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
2959 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;2962 u32 plen = le32_to_cpu(io->OutputCount);
2960 struct cifs_open_parms oparms;
2961 struct cifs_fid fid;
2962 struct kvec err_iov = {NULL, 0};
2963 struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
2964 int flags = CIFS_CP_CREATE_CLOSE_OP;
2965 struct smb_rqst rqst[3];
2966 int resp_buftype[3];
2967 struct kvec rsp_iov[3];
2968 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
2969 struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
2970 struct kvec close_iov[1];
2971 struct smb2_create_rsp *create_rsp;
2972 struct smb2_ioctl_rsp *ioctl_rsp;
2973 struct reparse_data_buffer *reparse_buf;
2974 int create_options = is_reparse_point ? OPEN_REPARSE_POINT : 0;
2975 u32 plen;
2976 2963
2977 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);2964 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
2978 2965
2979 *target_path = NULL;2966 buf = (struct reparse_data_buffer *)((u8 *)io +
2980 2967 le32_to_cpu(io->OutputOffset));
2981 if (smb3_encryption_required(tcon))2968 return parse_reparse_point(buf, plen, target_path, cifs_sb);
2982 flags |= CIFS_TRANSFORM_REQ;
2983
2984 memset(rqst, 0, sizeof(rqst));
2985 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
2986 memset(rsp_iov, 0, sizeof(rsp_iov));
2987
2988 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
2989 if (!utf16_path)
2990 return -ENOMEM;
2991
2992 /* Open */
2993 memset(&open_iov, 0, sizeof(open_iov));
2994 rqst[0].rq_iov = open_iov;
2995 rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
2996
2997 oparms = (struct cifs_open_parms) {
2998 .tcon = tcon,
2999 .path = full_path,
3000 .desired_access = FILE_READ_ATTRIBUTES,
3001 .disposition = FILE_OPEN,
3002 .create_options = cifs_create_options(cifs_sb, create_options),
3003 .fid = &fid,
3004 };
3005
3006 rc = SMB2_open_init(tcon, server,
3007 &rqst[0], &oplock, &oparms, utf16_path);
3008 if (rc)
3009 goto querty_exit;
3010 smb2_set_next_command(tcon, &rqst[0]);
3011
3012
3013 /* IOCTL */
3014 memset(&io_iov, 0, sizeof(io_iov));
3015 rqst[1].rq_iov = io_iov;
3016 rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
3017
3018 rc = SMB2_ioctl_init(tcon, server,
3019 &rqst[1], fid.persistent_fid,
3020 fid.volatile_fid, FSCTL_GET_REPARSE_POINT, NULL, 0,
3021 CIFSMaxBufSize -
3022 MAX_SMB2_CREATE_RESPONSE_SIZE -
3023 MAX_SMB2_CLOSE_RESPONSE_SIZE);
3024 if (rc)
3025 goto querty_exit;
3026
3027 smb2_set_next_command(tcon, &rqst[1]);
3028 smb2_set_related(&rqst[1]);
3029
3030
3031 /* Close */
3032 memset(&close_iov, 0, sizeof(close_iov));
3033 rqst[2].rq_iov = close_iov;
3034 rqst[2].rq_nvec = 1;
3035
3036 rc = SMB2_close_init(tcon, server,
3037 &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
3038 if (rc)
3039 goto querty_exit;
3040
3041 smb2_set_related(&rqst[2]);
3042
3043 rc = compound_send_recv(xid, tcon->ses, server,
3044 flags, 3, rqst,
3045 resp_buftype, rsp_iov);
3046
3047 create_rsp = rsp_iov[0].iov_base;
3048 if (create_rsp && create_rsp->hdr.Status)
3049 err_iov = rsp_iov[0];
3050 ioctl_rsp = rsp_iov[1].iov_base;
3051
3052 /*
3053 * Open was successful and we got an ioctl response.
3054 */
3055 if ((rc == 0) && (is_reparse_point)) {
3056 /* See MS-FSCC 2.3.23 */
3057
3058 reparse_buf = (struct reparse_data_buffer *)
3059 ((char *)ioctl_rsp +
3060 le32_to_cpu(ioctl_rsp->OutputOffset));
3061 plen = le32_to_cpu(ioctl_rsp->OutputCount);
3062
3063 if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
3064 rsp_iov[1].iov_len) {
3065 cifs_tcon_dbg(VFS, "srv returned invalid ioctl len: %d\n",
3066 plen);
3067 rc = -EIO;
3068 goto querty_exit;
3069 }
3070
3071 rc = parse_reparse_point(reparse_buf, plen, target_path,
3072 cifs_sb);
3073 goto querty_exit;
3074 }
3075
3076 if (!rc || !err_iov.iov_base) {
3077 rc = -ENOENT;
3078 goto querty_exit;
3079 }
3080
3081 rc = smb2_parse_symlink_response(cifs_sb, &err_iov, target_path);
3082
3083 querty_exit:
3084 cifs_dbg(FYI, "query symlink rc %d\n", rc);
3085 kfree(utf16_path);
3086 SMB2_open_free(&rqst[0]);
3087 SMB2_ioctl_free(&rqst[1]);
3088 SMB2_close_free(&rqst[2]);
3089 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
3090 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
3091 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
3092 return rc;
3093}2969}
3094 2970
3095int2971static int smb2_query_reparse_point(const unsigned int xid,
3096smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,2972 struct cifs_tcon *tcon,
3097 struct cifs_sb_info *cifs_sb, const char *full_path,2973 struct cifs_sb_info *cifs_sb,
3098 __u32 *tag)2974 const char *full_path,
2975 u32 *tag, struct kvec *rsp,
2976 int *rsp_buftype)
3099{2977{
2978 struct smb2_compound_vars *vars;
3100 int rc;2979 int rc;
3101 __le16 *utf16_path = NULL;2980 __le16 *utf16_path = NULL;
3102 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;2981 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
@@ -3104,12 +2983,9 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, · 1 unmodified line
3104 struct cifs_fid fid;2983 struct cifs_fid fid;
3105 struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);2984 struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
3106 int flags = CIFS_CP_CREATE_CLOSE_OP;2985 int flags = CIFS_CP_CREATE_CLOSE_OP;
3107 struct smb_rqst rqst[3];2986 struct smb_rqst *rqst;
3108 int resp_buftype[3];2987 int resp_buftype[3];
3109 struct kvec rsp_iov[3];2988 struct kvec *rsp_iov;
3110 struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
3111 struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
3112 struct kvec close_iov[1];
3113 struct smb2_ioctl_rsp *ioctl_rsp;2989 struct smb2_ioctl_rsp *ioctl_rsp;
3114 struct reparse_data_buffer *reparse_buf;2990 struct reparse_data_buffer *reparse_buf;
3115 u32 plen;2991 u32 plen;
@@ -3119,20 +2995,24 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, · 3 unmodified lines
3119 if (smb3_encryption_required(tcon))2995 if (smb3_encryption_required(tcon))
3120 flags |= CIFS_TRANSFORM_REQ;2996 flags |= CIFS_TRANSFORM_REQ;
3121 2997
3122 memset(rqst, 0, sizeof(rqst));
3123 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
3124 memset(rsp_iov, 0, sizeof(rsp_iov));
3125
3126 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);2998 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
3127 if (!utf16_path)2999 if (!utf16_path)
3128 return -ENOMEM;3000 return -ENOMEM;
3129 3001
3002 resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
3003 vars = kzalloc(sizeof(*vars), GFP_KERNEL);
3004 if (!vars) {
3005 rc = -ENOMEM;
3006 goto out_free_path;
3007 }
3008 rqst = vars->rqst;
3009 rsp_iov = vars->rsp_iov;
3010
3130 /*3011 /*
3131 * setup smb2open - TODO add optimization to call cifs_get_readable_path3012 * setup smb2open - TODO add optimization to call cifs_get_readable_path
3132 * to see if there is a handle already open that we can use3013 * to see if there is a handle already open that we can use
3133 */3014 */
3134 memset(&open_iov, 0, sizeof(open_iov));3015 rqst[0].rq_iov = vars->open_iov;
3135 rqst[0].rq_iov = open_iov;
3136 rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;3016 rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
3137 3017
3138 oparms = (struct cifs_open_parms) {3018 oparms = (struct cifs_open_parms) {
@@ -3152,8 +3032,7 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, · 13 unmodified lines
3152 3032
3153 3033
3154 /* IOCTL */3034 /* IOCTL */
3155 memset(&io_iov, 0, sizeof(io_iov));3035 rqst[1].rq_iov = vars->io_iov;
3156 rqst[1].rq_iov = io_iov;
3157 rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;3036 rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
3158 3037
3159 rc = SMB2_ioctl_init(tcon, server,3038 rc = SMB2_ioctl_init(tcon, server,
@@ -3168,10 +3047,8 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, · 8 unmodified lines
3168 smb2_set_next_command(tcon, &rqst[1]);3047 smb2_set_next_command(tcon, &rqst[1]);
3169 smb2_set_related(&rqst[1]);3048 smb2_set_related(&rqst[1]);
3170 3049
3171
3172 /* Close */3050 /* Close */
3173 memset(&close_iov, 0, sizeof(close_iov));3051 rqst[2].rq_iov = &vars->close_iov;
3174 rqst[2].rq_iov = close_iov;
3175 rqst[2].rq_nvec = 1;3052 rqst[2].rq_nvec = 1;
3176 3053
3177 rc = SMB2_close_init(tcon, server,3054 rc = SMB2_close_init(tcon, server,
@@ -3206,16 +3083,21 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, · 28 unmodified lines
3206 goto query_rp_exit;3083 goto query_rp_exit;
3207 }3084 }
3208 *tag = le32_to_cpu(reparse_buf->ReparseTag);3085 *tag = le32_to_cpu(reparse_buf->ReparseTag);
3086 *rsp = rsp_iov[1];
3087 *rsp_buftype = resp_buftype[1];
3088 resp_buftype[1] = CIFS_NO_BUFFER;
3209 }3089 }
3210 3090
3211 query_rp_exit:3091 query_rp_exit:
3212 kfree(utf16_path);
3213 SMB2_open_free(&rqst[0]);3092 SMB2_open_free(&rqst[0]);
3214 SMB2_ioctl_free(&rqst[1]);3093 SMB2_ioctl_free(&rqst[1]);
3215 SMB2_close_free(&rqst[2]);3094 SMB2_close_free(&rqst[2]);
3216 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);3095 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
3217 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);3096 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
3218 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);3097 free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
3098 kfree(vars);
3099out_free_path:
3100 kfree(utf16_path);
3219 return rc;3101 return rc;
3220}3102}
3221 3103
@@ -4401,7 +4283,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) · 1179 unmodified lines
4401 u8 *ses_enc_key;4283 u8 *ses_enc_key;
4402 4284
4403 /* If server is a channel, select the primary channel */4285 /* If server is a channel, select the primary channel */
4404 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;4286 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
4405 4287
4406 spin_lock(&cifs_tcp_ses_lock);4288 spin_lock(&cifs_tcp_ses_lock);
4407 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {4289 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
@@ -5299,6 +5181,7 @@ struct smb_version_operations smb20_operations = { · 891 unmodified lines
5299 .can_echo = smb2_can_echo,5181 .can_echo = smb2_can_echo,
5300 .echo = SMB2_echo,5182 .echo = SMB2_echo,
5301 .query_path_info = smb2_query_path_info,5183 .query_path_info = smb2_query_path_info,
5184 .query_reparse_point = smb2_query_reparse_point,
5302 .get_srv_inum = smb2_get_srv_inum,5185 .get_srv_inum = smb2_get_srv_inum,
5303 .query_file_info = smb2_query_file_info,5186 .query_file_info = smb2_query_file_info,
5304 .set_path_size = smb2_set_path_size,5187 .set_path_size = smb2_set_path_size,
@@ -5400,6 +5283,7 @@ struct smb_version_operations smb21_operations = { · 95 unmodified lines
5400 .can_echo = smb2_can_echo,5283 .can_echo = smb2_can_echo,
5401 .echo = SMB2_echo,5284 .echo = SMB2_echo,
5402 .query_path_info = smb2_query_path_info,5285 .query_path_info = smb2_query_path_info,
5286 .query_reparse_point = smb2_query_reparse_point,
5403 .get_srv_inum = smb2_get_srv_inum,5287 .get_srv_inum = smb2_get_srv_inum,
5404 .query_file_info = smb2_query_file_info,5288 .query_file_info = smb2_query_file_info,
5405 .set_path_size = smb2_set_path_size,5289 .set_path_size = smb2_set_path_size,
@@ -5504,7 +5388,7 @@ struct smb_version_operations smb30_operations = { · 98 unmodified lines
5504 .echo = SMB2_echo,5388 .echo = SMB2_echo,
5505 .query_path_info = smb2_query_path_info,5389 .query_path_info = smb2_query_path_info,
5506 /* WSL tags introduced long after smb2.1, enable for SMB3, 3.11 only */5390 /* WSL tags introduced long after smb2.1, enable for SMB3, 3.11 only */
5507 .query_reparse_tag = smb2_query_reparse_tag,5391 .query_reparse_point = smb2_query_reparse_point,
5508 .get_srv_inum = smb2_get_srv_inum,5392 .get_srv_inum = smb2_get_srv_inum,
5509 .query_file_info = smb2_query_file_info,5393 .query_file_info = smb2_query_file_info,
5510 .set_path_size = smb2_set_path_size,5394 .set_path_size = smb2_set_path_size,
@@ -5617,7 +5501,7 @@ struct smb_version_operations smb311_operations = { · 106 unmodified lines
5617 .can_echo = smb2_can_echo,5501 .can_echo = smb2_can_echo,
5618 .echo = SMB2_echo,5502 .echo = SMB2_echo,
5619 .query_path_info = smb2_query_path_info,5503 .query_path_info = smb2_query_path_info,
5620 .query_reparse_tag = smb2_query_reparse_tag,5504 .query_reparse_point = smb2_query_reparse_point,
5621 .get_srv_inum = smb2_get_srv_inum,5505 .get_srv_inum = smb2_get_srv_inum,
5622 .query_file_info = smb2_query_file_info,5506 .query_file_info = smb2_query_file_info,
5623 .set_path_size = smb2_set_path_size,5507 .set_path_size = smb2_set_path_size,
fs/smb/client/smb2pdu.c+15−4
@@ -88,9 +88,20 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd, · 87 unmodified lines
88 const struct cifs_tcon *tcon,88 const struct cifs_tcon *tcon,
89 struct TCP_Server_Info *server)89 struct TCP_Server_Info *server)
90{90{
91 struct smb3_hdr_req *smb3_hdr;
91 shdr->ProtocolId = SMB2_PROTO_NUMBER;92 shdr->ProtocolId = SMB2_PROTO_NUMBER;
92 shdr->StructureSize = cpu_to_le16(64);93 shdr->StructureSize = cpu_to_le16(64);
93 shdr->Command = smb2_cmd;94 shdr->Command = smb2_cmd;
95 if (server->dialect >= SMB30_PROT_ID) {
96 /* After reconnect SMB3 must set ChannelSequence on subsequent reqs */
97 smb3_hdr = (struct smb3_hdr_req *)shdr;
98 /* if primary channel is not set yet, use default channel for chan sequence num */
99 if (SERVER_IS_CHAN(server))
100 smb3_hdr->ChannelSequence =
101 cpu_to_le16(server->primary_server->channel_sequence_num);
102 else
103 smb3_hdr->ChannelSequence = cpu_to_le16(server->channel_sequence_num);
104 }
94 if (server) {105 if (server) {
95 spin_lock(&server->req_lock);106 spin_lock(&server->req_lock);
96 /* Request up to 10 credits but don't go over the limit. */107 /* Request up to 10 credits but don't go over the limit. */
@@ -553,7 +564,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, · 456 unmodified lines
553 * secondary channels don't have the hostname field populated564 * secondary channels don't have the hostname field populated
554 * use the hostname field in the primary channel instead565 * use the hostname field in the primary channel instead
555 */566 */
556 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;567 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
557 cifs_server_lock(pserver);568 cifs_server_lock(pserver);
558 hostname = pserver->hostname;569 hostname = pserver->hostname;
559 if (hostname && (hostname[0] != 0)) {570 if (hostname && (hostname[0] != 0)) {
@@ -2570,8 +2581,8 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len, · 2010 unmodified lines
2570 2581
2571 /* Do not append the separator if the path is empty */2582 /* Do not append the separator if the path is empty */
2572 if (path[0] != cpu_to_le16(0x0000)) {2583 if (path[0] != cpu_to_le16(0x0000)) {
2573 UniStrcat(*out_path, sep);2584 UniStrcat((wchar_t *)*out_path, (wchar_t *)sep);
2574 UniStrcat(*out_path, path);2585 UniStrcat((wchar_t *)*out_path, (wchar_t *)path);
2575 }2586 }
2576 2587
2577 unload_nls(cp);2588 unload_nls(cp);
@@ -3785,7 +3796,7 @@ void smb2_reconnect_server(struct work_struct *work) · 1207 unmodified lines
3785 bool resched = false;3796 bool resched = false;
3786 3797
3787 /* If server is a channel, select the primary channel */3798 /* If server is a channel, select the primary channel */
3788 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;3799 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
3789 3800
3790 /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */3801 /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
3791 mutex_lock(&pserver->reconnect_mutex);3802 mutex_lock(&pserver->reconnect_mutex);
fs/smb/client/smb2proto.h+10−7
@@ -56,9 +56,11 @@ extern int smb3_handle_read_data(struct TCP_Server_Info *server, · 55 unmodified lines
56extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,56extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
57 struct cifs_sb_info *cifs_sb, const char *path,57 struct cifs_sb_info *cifs_sb, const char *path,
58 __u32 *reparse_tag);58 __u32 *reparse_tag);
59int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,59int smb2_query_path_info(const unsigned int xid,
60 struct cifs_sb_info *cifs_sb, const char *full_path,60 struct cifs_tcon *tcon,
61 struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);61 struct cifs_sb_info *cifs_sb,
62 const char *full_path,
63 struct cifs_open_info_data *data);
62extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,64extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
63 const char *full_path, __u64 size,65 const char *full_path, __u64 size,
64 struct cifs_sb_info *cifs_sb, bool set_alloc);66 struct cifs_sb_info *cifs_sb, bool set_alloc);
@@ -275,12 +277,13 @@ extern int smb2_query_info_compound(const unsigned int xid, · 210 unmodified lines
275 struct kvec *rsp, int *buftype,277 struct kvec *rsp, int *buftype,
276 struct cifs_sb_info *cifs_sb);278 struct cifs_sb_info *cifs_sb);
277/* query path info from the server using SMB311 POSIX extensions*/279/* query path info from the server using SMB311 POSIX extensions*/
278int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,280int smb311_posix_query_path_info(const unsigned int xid,
279 struct cifs_sb_info *cifs_sb, const char *full_path,281 struct cifs_tcon *tcon,
282 struct cifs_sb_info *cifs_sb,
283 const char *full_path,
280 struct cifs_open_info_data *data,284 struct cifs_open_info_data *data,
281 struct cifs_sid *owner,285 struct cifs_sid *owner,
282 struct cifs_sid *group,286 struct cifs_sid *group);
283 bool *adjust_tz, bool *reparse);
284int posix_info_parse(const void *beg, const void *end,287int posix_info_parse(const void *beg, const void *end,
285 struct smb2_posix_info_parsed *out);288 struct smb2_posix_info_parsed *out);
286int posix_info_sid_size(const void *beg, const void *end);289int posix_info_sid_size(const void *beg, const void *end);
fs/smb/client/smb2transport.c+2−2
@@ -86,7 +86,7 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key) · 85 unmodified lines
86 spin_lock(&cifs_tcp_ses_lock);86 spin_lock(&cifs_tcp_ses_lock);
87 87
88 /* If server is a channel, select the primary channel */88 /* If server is a channel, select the primary channel */
89 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;89 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
90 90
91 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {91 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
92 if (ses->Suid == ses_id)92 if (ses->Suid == ses_id)
@@ -149,7 +149,7 @@ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id) · 56 unmodified lines
149 struct cifs_ses *ses;149 struct cifs_ses *ses;
150 150
151 /* If server is a channel, select the primary channel */151 /* If server is a channel, select the primary channel */
152 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;152 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
153 153
154 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {154 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
155 if (ses->Suid != ses_id)155 if (ses->Suid != ses_id)
fs/smb/client/transport.c+17−12
@@ -416,13 +416,19 @@ out: · 415 unmodified lines
416 return rc;416 return rc;
417}417}
418 418
419struct send_req_vars {
420 struct smb2_transform_hdr tr_hdr;
421 struct smb_rqst rqst[MAX_COMPOUND];
422 struct kvec iov;
423};
424
419static int425static int
420smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,426smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
421 struct smb_rqst *rqst, int flags)427 struct smb_rqst *rqst, int flags)
422{428{
423 struct kvec iov;429 struct send_req_vars *vars;
424 struct smb2_transform_hdr *tr_hdr;430 struct smb_rqst *cur_rqst;
425 struct smb_rqst cur_rqst[MAX_COMPOUND];431 struct kvec *iov;
426 int rc;432 int rc;
427 433
428 if (!(flags & CIFS_TRANSFORM_REQ))434 if (!(flags & CIFS_TRANSFORM_REQ))
@@ -436,16 +442,15 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, · 7 unmodified lines
436 return -EIO;442 return -EIO;
437 }443 }
438 444
439 tr_hdr = kzalloc(sizeof(*tr_hdr), GFP_NOFS);445 vars = kzalloc(sizeof(*vars), GFP_NOFS);
440 if (!tr_hdr)446 if (!vars)
441 return -ENOMEM;447 return -ENOMEM;
448 cur_rqst = vars->rqst;
449 iov = &vars->iov;
442 450
443 memset(&cur_rqst[0], 0, sizeof(cur_rqst));451 iov->iov_base = &vars->tr_hdr;
444 memset(&iov, 0, sizeof(iov));452 iov->iov_len = sizeof(vars->tr_hdr);
445 453 cur_rqst[0].rq_iov = iov;
446 iov.iov_base = tr_hdr;
447 iov.iov_len = sizeof(*tr_hdr);
448 cur_rqst[0].rq_iov = &iov;
449 cur_rqst[0].rq_nvec = 1;454 cur_rqst[0].rq_nvec = 1;
450 455
451 rc = server->ops->init_transform_rq(server, num_rqst + 1,456 rc = server->ops->init_transform_rq(server, num_rqst + 1,
@@ -456,7 +461,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, · 4 unmodified lines
456 rc = __smb_send_rqst(server, num_rqst + 1, &cur_rqst[0]);461 rc = __smb_send_rqst(server, num_rqst + 1, &cur_rqst[0]);
457 smb3_free_compound_rqst(num_rqst, &cur_rqst[1]);462 smb3_free_compound_rqst(num_rqst, &cur_rqst[1]);
458out:463out:
459 kfree(tr_hdr);464 kfree(vars);
460 return rc;465 return rc;
461}466}
462 467
fs/smb/common/smb2pdu.h+22−0
@@ -153,6 +153,28 @@ struct smb2_hdr { · 152 unmodified lines
153 __u8 Signature[16];153 __u8 Signature[16];
154} __packed;154} __packed;
155 155
156struct smb3_hdr_req {
157 __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */
158 __le16 StructureSize; /* 64 */
159 __le16 CreditCharge; /* MBZ */
160 __le16 ChannelSequence; /* See MS-SMB2 3.2.4.1 and 3.2.7.1 */
161 __le16 Reserved;
162 __le16 Command;
163 __le16 CreditRequest; /* CreditResponse */
164 __le32 Flags;
165 __le32 NextCommand;
166 __le64 MessageId;
167 union {
168 struct {
169 __le32 ProcessId;
170 __le32 TreeId;
171 } __packed SyncId;
172 __le64 AsyncId;
173 } __packed Id;
174 __le64 SessionId;
175 __u8 Signature[16];
176} __packed;
177
156struct smb2_pdu {178struct smb2_pdu {
157 struct smb2_hdr hdr;179 struct smb2_hdr hdr;
158 __le16 StructureSize2; /* size of wct area (varies, request specific) */180 __le16 StructureSize2; /* size of wct area (varies, request specific) */
fs/smb/server/Kconfig+1−0
@@ -5,6 +5,7 @@ config SMB_SERVER · 4 unmodified lines
5 depends on FILE_LOCKING5 depends on FILE_LOCKING
6 select NLS6 select NLS
7 select NLS_UTF87 select NLS_UTF8
8 select NLS_UCS2_UTILS
8 select CRYPTO9 select CRYPTO
9 select CRYPTO_MD510 select CRYPTO_MD5
10 select CRYPTO_HMAC11 select CRYPTO_HMAC
fs/smb/server/unicode.c+0−1
@@ -11,7 +11,6 @@ · 10 unmodified lines
11#include <asm/unaligned.h>11#include <asm/unaligned.h>
12#include "glob.h"12#include "glob.h"
13#include "unicode.h"13#include "unicode.h"
14#include "uniupr.h"
15#include "smb_common.h"14#include "smb_common.h"
16 15
17/*16/*
fs/smb/server/unicode.h+4−321
@@ -18,49 +18,14 @@ · 17 unmodified lines
18 * This is a compressed table of upper and lower case conversion.18 * This is a compressed table of upper and lower case conversion.
19 *19 *
20 */20 */
21#ifndef _CIFS_UNICODE_H21#ifndef _SMB_UNICODE_H
22#define _CIFS_UNICODE_H22#define _SMB_UNICODE_H
23 23
24#include <asm/byteorder.h>24#include <asm/byteorder.h>
25#include <linux/types.h>25#include <linux/types.h>
26#include <linux/nls.h>26#include <linux/nls.h>
27#include <linux/unicode.h>27#include <linux/unicode.h>
28 28#include "../../nls/nls_ucs2_utils.h"
29#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
30
31/*
32 * Windows maps these to the user defined 16 bit Unicode range since they are
33 * reserved symbols (along with \ and /), otherwise illegal to store
34 * in filenames in NTFS
35 */
36#define UNI_ASTERISK ((__u16)('*' + 0xF000))
37#define UNI_QUESTION ((__u16)('?' + 0xF000))
38#define UNI_COLON ((__u16)(':' + 0xF000))
39#define UNI_GRTRTHAN ((__u16)('>' + 0xF000))
40#define UNI_LESSTHAN ((__u16)('<' + 0xF000))
41#define UNI_PIPE ((__u16)('|' + 0xF000))
42#define UNI_SLASH ((__u16)('\\' + 0xF000))
43
44/* Just define what we want from uniupr.h. We don't want to define the tables
45 * in each source file.
46 */
47#ifndef UNICASERANGE_DEFINED
48struct UniCaseRange {
49 wchar_t start;
50 wchar_t end;
51 signed char *table;
52};
53#endif /* UNICASERANGE_DEFINED */
54
55#ifndef UNIUPR_NOUPPER
56extern signed char SmbUniUpperTable[512];
57extern const struct UniCaseRange SmbUniUpperRange[];
58#endif /* UNIUPR_NOUPPER */
59
60#ifndef UNIUPR_NOLOWER
61extern signed char CifsUniLowerTable[512];
62extern const struct UniCaseRange CifsUniLowerRange[];
63#endif /* UNIUPR_NOLOWER */
64 29
65#ifdef __KERNEL__30#ifdef __KERNEL__
66int smb_strtoUTF16(__le16 *to, const char *from, int len,31int smb_strtoUTF16(__le16 *to, const char *from, int len,
@@ -73,286 +38,4 @@ int smbConvertToUTF16(__le16 *target, const char *source, int srclen, · 6 unmodified lines
73char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);38char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
74#endif39#endif
75 40
76/*41#endif /* _SMB_UNICODE_H */
77 * UniStrcat: Concatenate the second string to the first
78 *
79 * Returns:
80 * Address of the first string
81 */
82static inline wchar_t *UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
83{
84 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
85
86 while (*ucs1++)
87 /*NULL*/; /* To end of first string */
88 ucs1--; /* Return to the null */
89 while ((*ucs1++ = *ucs2++))
90 /*NULL*/; /* copy string 2 over */
91 return anchor;
92}
93
94/*
95 * UniStrchr: Find a character in a string
96 *
97 * Returns:
98 * Address of first occurrence of character in string
99 * or NULL if the character is not in the string
100 */
101static inline wchar_t *UniStrchr(const wchar_t *ucs, wchar_t uc)
102{
103 while ((*ucs != uc) && *ucs)
104 ucs++;
105
106 if (*ucs == uc)
107 return (wchar_t *)ucs;
108 return NULL;
109}
110
111/*
112 * UniStrcmp: Compare two strings
113 *
114 * Returns:
115 * < 0: First string is less than second
116 * = 0: Strings are equal
117 * > 0: First string is greater than second
118 */
119static inline int UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
120{
121 while ((*ucs1 == *ucs2) && *ucs1) {
122 ucs1++;
123 ucs2++;
124 }
125 return (int)*ucs1 - (int)*ucs2;
126}
127
128/*
129 * UniStrcpy: Copy a string
130 */
131static inline wchar_t *UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
132{
133 wchar_t *anchor = ucs1; /* save the start of result string */
134
135 while ((*ucs1++ = *ucs2++))
136 /*NULL*/;
137 return anchor;
138}
139
140/*
141 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
142 */
143static inline size_t UniStrlen(const wchar_t *ucs1)
144{
145 int i = 0;
146
147 while (*ucs1++)
148 i++;
149 return i;
150}
151
152/*
153 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
154 * string (length limited)
155 */
156static inline size_t UniStrnlen(const wchar_t *ucs1, int maxlen)
157{
158 int i = 0;
159
160 while (*ucs1++) {
161 i++;
162 if (i >= maxlen)
163 break;
164 }
165 return i;
166}
167
168/*
169 * UniStrncat: Concatenate length limited string
170 */
171static inline wchar_t *UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
172{
173 wchar_t *anchor = ucs1; /* save pointer to string 1 */
174
175 while (*ucs1++)
176 /*NULL*/;
177 ucs1--; /* point to null terminator of s1 */
178 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
179 ucs1++;
180 ucs2++;
181 }
182 *ucs1 = 0; /* Null terminate the result */
183 return anchor;
184}
185
186/*
187 * UniStrncmp: Compare length limited string
188 */
189static inline int UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
190{
191 if (!n)
192 return 0; /* Null strings are equal */
193 while ((*ucs1 == *ucs2) && *ucs1 && --n) {
194 ucs1++;
195 ucs2++;
196 }
197 return (int)*ucs1 - (int)*ucs2;
198}
199
200/*
201 * UniStrncmp_le: Compare length limited string - native to little-endian
202 */
203static inline int
204UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
205{
206 if (!n)
207 return 0; /* Null strings are equal */
208 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
209 ucs1++;
210 ucs2++;
211 }
212 return (int)*ucs1 - (int)__le16_to_cpu(*ucs2);
213}
214
215/*
216 * UniStrncpy: Copy length limited string with pad
217 */
218static inline wchar_t *UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
219{
220 wchar_t *anchor = ucs1;
221
222 while (n-- && *ucs2) /* Copy the strings */
223 *ucs1++ = *ucs2++;
224
225 n++;
226 while (n--) /* Pad with nulls */
227 *ucs1++ = 0;
228 return anchor;
229}
230
231/*
232 * UniStrncpy_le: Copy length limited string with pad to little-endian
233 */
234static inline wchar_t *UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
235{
236 wchar_t *anchor = ucs1;
237
238 while (n-- && *ucs2) /* Copy the strings */
239 *ucs1++ = __le16_to_cpu(*ucs2++);
240
241 n++;
242 while (n--) /* Pad with nulls */
243 *ucs1++ = 0;
244 return anchor;
245}
246
247/*
248 * UniStrstr: Find a string in a string
249 *
250 * Returns:
251 * Address of first match found
252 * NULL if no matching string is found
253 */
254static inline wchar_t *UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
255{
256 const wchar_t *anchor1 = ucs1;
257 const wchar_t *anchor2 = ucs2;
258
259 while (*ucs1) {
260 if (*ucs1 == *ucs2) {
261 /* Partial match found */
262 ucs1++;
263 ucs2++;
264 } else {
265 if (!*ucs2) /* Match found */
266 return (wchar_t *)anchor1;
267 ucs1 = ++anchor1; /* No match */
268 ucs2 = anchor2;
269 }
270 }
271
272 if (!*ucs2) /* Both end together */
273 return (wchar_t *)anchor1; /* Match found */
274 return NULL; /* No match */
275}
276
277#ifndef UNIUPR_NOUPPER
278/*
279 * UniToupper: Convert a unicode character to upper case
280 */
281static inline wchar_t UniToupper(register wchar_t uc)
282{
283 register const struct UniCaseRange *rp;
284
285 if (uc < sizeof(SmbUniUpperTable)) {
286 /* Latin characters */
287 return uc + SmbUniUpperTable[uc]; /* Use base tables */
288 }
289
290 rp = SmbUniUpperRange; /* Use range tables */
291 while (rp->start) {
292 if (uc < rp->start) /* Before start of range */
293 return uc; /* Uppercase = input */
294 if (uc <= rp->end) /* In range */
295 return uc + rp->table[uc - rp->start];
296 rp++; /* Try next range */
297 }
298 return uc; /* Past last range */
299}
300
301/*
302 * UniStrupr: Upper case a unicode string
303 */
304static inline __le16 *UniStrupr(register __le16 *upin)
305{
306 register __le16 *up;
307
308 up = upin;
309 while (*up) { /* For all characters */
310 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
311 up++;
312 }
313 return upin; /* Return input pointer */
314}
315#endif /* UNIUPR_NOUPPER */
316
317#ifndef UNIUPR_NOLOWER
318/*
319 * UniTolower: Convert a unicode character to lower case
320 */
321static inline wchar_t UniTolower(register wchar_t uc)
322{
323 register const struct UniCaseRange *rp;
324
325 if (uc < sizeof(CifsUniLowerTable)) {
326 /* Latin characters */
327 return uc + CifsUniLowerTable[uc]; /* Use base tables */
328 }
329
330 rp = CifsUniLowerRange; /* Use range tables */
331 while (rp->start) {
332 if (uc < rp->start) /* Before start of range */
333 return uc; /* Uppercase = input */
334 if (uc <= rp->end) /* In range */
335 return uc + rp->table[uc - rp->start];
336 rp++; /* Try next range */
337 }
338 return uc; /* Past last range */
339}
340
341/*
342 * UniStrlwr: Lower case a unicode string
343 */
344static inline wchar_t *UniStrlwr(register wchar_t *upin)
345{
346 register wchar_t *up;
347
348 up = upin;
349 while (*up) { /* For all characters */
350 *up = UniTolower(*up);
351 up++;
352 }
353 return upin; /* Return input pointer */
354}
355
356#endif
357
358#endif /* _CIFS_UNICODE_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t