Skip to content

Commit

Permalink
Merge tag '4.18-rc1-more-smb3-fixes' of git://git.samba.org/sfrench/c…
Browse files Browse the repository at this point in the history
…ifs-2.6

Pull cifs fixes from Steve French:
 "Misc SMB3 fixes, including particularly important ones for signing,
  some minor documentation and debug improvements and another posix
  smb3.11 fix"

* tag '4.18-rc1-more-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: Fix invalid check in __cifs_calc_signature()
  cifs: Use correct packet length in SMB2_TRANSFORM header
  smb3: fix corrupt path in subdirs on smb311 with posix
  smb3: do not display empty interface list
  smb3: Fix mode on mkdir on smb311 mounts
  cifs: Fix kernel oops when traceSMB is enabled
  CIFS: dump every session iface info
  CIFS: parse and store info on iface queries
  CIFS: add iface info to struct cifs_ses
  CIFS: complete PDU definitions for interface queries
  CIFS: move default port definitions to cifsglob.h
  cifs: Fix encryption/signing
  cifs: update __smb_send_rqst() to take an array of requests
  cifs: remove smb2_send_recv()
  cifs: push rfc1002 generation down the stack
  smb3: increase initial number of credits requested to allow write
  cifs: minor documentation updates
  cifs: add lease tracking to the cached root fid
  smb3: note that smb3.11 posix extensions mount option is experimental
  • Loading branch information
Linus Torvalds committed Jun 18, 2018
2 parents a569631 + 83ffdea commit 9ffc59d
Show file tree
Hide file tree
Showing 20 changed files with 753 additions and 279 deletions.
7 changes: 4 additions & 3 deletions Documentation/filesystems/cifs/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
Scott Lovenberg
Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features)
Aurelien Aptel (for DFS SMB3 work and some key bug fixes)
Ronnie Sahlberg (for SMB3 xattr work and bug fixes)
Ronnie Sahlberg (for SMB3 xattr work, bug fixes, and lots of great work on compounding)
Shirish Pargaonkar (for many ACL patches over the years)
Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security)
Paulo Alcantara
Long Li (some great work on RDMA, SMB Direct)


Test case and Bug Report contributors
Expand All @@ -58,5 +60,4 @@ mention to the Stanford Checker (SWAT) which pointed out many minor
bugs in error paths. Valuable suggestions also have come from Al Viro
and Dave Miller.

And thanks to the IBM LTC and Power test teams and SuSE testers for
finding multiple bugs during excellent stress test runs.
And thanks to the IBM LTC and Power test teams and SuSE and Citrix and RedHat testers for finding multiple bugs during excellent stress test runs.
3 changes: 3 additions & 0 deletions Documentation/filesystems/cifs/CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
See https://wiki.samba.org/index.php/LinuxCIFSKernel for
more current information.

Version 1.62
------------
Add sockopt=TCP_NODELAY mount option. EA (xattr) routines hardened
Expand Down
17 changes: 9 additions & 8 deletions Documentation/filesystems/cifs/TODO
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ is a partial list of the known problems and missing features:

a) SMB3 (and SMB3.02) missing optional features:
- multichannel (started), integration with RDMA
- directory leases (improved metadata caching)
- T10 copy offload (copy chunk, and "Duplicate Extents" ioctl
- directory leases (improved metadata caching), started (root dir only)
- T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
currently the only two server side copy mechanisms supported)

b) improved sparse file support

c) Directory entry caching relies on a 1 second timer, rather than
using Directory Leases
using Directory Leases, currently only the root file handle is cached longer

d) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems)
Expand All @@ -42,6 +42,8 @@ mount or a per server basis to client UIDs or nobody if no mapping
exists. Also better integration with winbind for resolving SID owners

k) Add tools to take advantage of more smb3 specific ioctls and features
(passthrough ioctl/fsctl for sending various SMB3 fsctls to the server
is in progress)

l) encrypted file support

Expand Down Expand Up @@ -71,9 +73,8 @@ t) split cifs and smb3 support into separate modules so legacy (and less
secure) CIFS dialect can be disabled in environments that don't need it
and simplify the code.

u) Finish up SMB3.1.1 dialect support

v) POSIX Extensions for SMB3.1.1
v) POSIX Extensions for SMB3.1.1 (started, create and mkdir support added
so far).

KNOWN BUGS
====================================
Expand All @@ -92,8 +93,8 @@ Misc testing to do
1) check out max path names and max path name components against various server
types. Try nested symlinks (8 deep). Return max path name in stat -f information

2) Improve xfstest's cifs enablement and adapt xfstests where needed to test
cifs better
2) Improve xfstest's cifs/smb3 enablement and adapt xfstests where needed to test
cifs/smb3 better

3) Additional performance testing and optimization using iozone and similar -
there are some easy changes that can be done to parallelize sequential writes,
Expand Down
29 changes: 29 additions & 0 deletions fs/cifs/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,25 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
seq_putc(m, '\n');
}

static void
cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface)
{
struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;

seq_printf(m, "\t\tSpeed: %zu bps\n", iface->speed);
seq_puts(m, "\t\tCapabilities: ");
if (iface->rdma_capable)
seq_puts(m, "rdma ");
if (iface->rss_capable)
seq_puts(m, "rss ");
seq_putc(m, '\n');
if (iface->sockaddr.ss_family == AF_INET)
seq_printf(m, "\t\tIPv4: %pI4\n", &ipv4->sin_addr);
else if (iface->sockaddr.ss_family == AF_INET6)
seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr);
}

static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
{
struct list_head *tmp1, *tmp2, *tmp3;
Expand Down Expand Up @@ -312,6 +331,16 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
mid_entry->mid);
}
spin_unlock(&GlobalMid_Lock);

spin_lock(&ses->iface_lock);
if (ses->iface_count)
seq_printf(m, "\n\tServer interfaces: %zu\n",
ses->iface_count);
for (j = 0; j < ses->iface_count; j++) {
seq_printf(m, "\t%d)\n", j);
cifs_dump_iface(m, &ses->iface_list[j]);
}
spin_unlock(&ses->iface_lock);
}
}
spin_unlock(&cifs_tcp_ses_lock);
Expand Down
20 changes: 15 additions & 5 deletions fs/cifs/cifsencrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,34 @@
#include <crypto/aead.h>

int __cifs_calc_signature(struct smb_rqst *rqst,
int start,
struct TCP_Server_Info *server, char *signature,
struct shash_desc *shash)
{
int i;
int rc;
struct kvec *iov = rqst->rq_iov;
int n_vec = rqst->rq_nvec;
int is_smb2 = server->vals->header_preamble_size == 0;

for (i = start; i < n_vec; i++) {
/* iov[0] is actual data and not the rfc1002 length for SMB2+ */
if (is_smb2) {
if (iov[0].iov_len <= 4)
return -EIO;
i = 0;
} else {
if (n_vec < 2 || iov[0].iov_len != 4)
return -EIO;
i = 1; /* skip rfc1002 length */
}

for (; i < n_vec; i++) {
if (iov[i].iov_len == 0)
continue;
if (iov[i].iov_base == NULL) {
cifs_dbg(VFS, "null iovec entry\n");
return -EIO;
}
if (i == 1 && iov[1].iov_len <= 4)
break; /* nothing to sign or corrupt header */

rc = crypto_shash_update(shash,
iov[i].iov_base, iov[i].iov_len);
if (rc) {
Expand Down Expand Up @@ -118,7 +128,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
return rc;
}

return __cifs_calc_signature(rqst, 1, server, signature,
return __cifs_calc_signature(rqst, server, signature,
&server->secmech.sdescmd5->shash);
}

Expand Down
40 changes: 37 additions & 3 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@

#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */

#define CIFS_PORT 445
#define RFC1001_PORT 139

/*
* The sizes of various internal tables and strings
*/
Expand Down Expand Up @@ -312,6 +315,10 @@ struct smb_version_operations {
/* send echo request */
int (*echo)(struct TCP_Server_Info *);
/* create directory */
int (*posix_mkdir)(const unsigned int xid, struct inode *inode,
umode_t mode, struct cifs_tcon *tcon,
const char *full_path,
struct cifs_sb_info *cifs_sb);
int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *,
struct cifs_sb_info *);
/* set info on created directory */
Expand Down Expand Up @@ -838,6 +845,13 @@ static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net)

#endif

struct cifs_server_iface {
size_t speed;
unsigned int rdma_capable : 1;
unsigned int rss_capable : 1;
struct sockaddr_storage sockaddr;
};

/*
* Session structure. One of these for each uid session with a particular host
*/
Expand Down Expand Up @@ -875,6 +889,20 @@ struct cifs_ses {
#ifdef CONFIG_CIFS_SMB311
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
#endif /* 3.1.1 */

/*
* Network interfaces available on the server this session is
* connected to.
*
* Other channels can be opened by connecting and binding this
* session to interfaces from this list.
*
* iface_lock should be taken when accessing any of these fields
*/
spinlock_t iface_lock;
struct cifs_server_iface *iface_list;
size_t iface_count;
unsigned long iface_last_update; /* jiffies */
};

static inline bool
Expand All @@ -883,6 +911,14 @@ cap_unix(struct cifs_ses *ses)
return ses->server->vals->cap_unix & ses->capabilities;
}

struct cached_fid {
bool is_valid:1; /* Do we have a useable root fid */
struct cifs_fid *fid;
struct mutex fid_mutex;
struct cifs_tcon *tcon;
struct work_struct lease_break;
};

/*
* there is one of these for each connection to a resource on a particular
* session
Expand Down Expand Up @@ -987,9 +1023,7 @@ struct cifs_tcon {
struct fscache_cookie *fscache; /* cookie for share */
#endif
struct list_head pending_opens; /* list of incomplete opens */
bool valid_root_fid:1; /* Do we have a useable root fid */
struct mutex prfid_mutex; /* prevents reopen race after dead ses*/
struct cifs_fid *prfid; /* handle to the directory at top of share */
struct cached_fid crfid; /* Cached root fid */
/* BB add field for back pointer to sb struct(s)? */
};

Expand Down
7 changes: 2 additions & 5 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,6 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */, const int flags,
struct kvec * /* resp vec */);
extern int smb2_send_recv(const unsigned int xid, struct cifs_ses *pses,
struct kvec *pkvec, int nvec_to_send,
int *pbuftype, const int flags,
struct kvec *presp);
extern int SendReceiveBlockingLock(const unsigned int xid,
struct cifs_tcon *ptcon,
struct smb_hdr *in_buf ,
Expand Down Expand Up @@ -544,14 +540,15 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
const unsigned char *path, char *pbuf,
unsigned int *pbytes_written);
int __cifs_calc_signature(struct smb_rqst *rqst, int start,
int __cifs_calc_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server, char *signature,
struct shash_desc *shash);
enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
enum securityEnum);
struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
void cifs_aio_ctx_release(struct kref *refcount);
int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
void smb2_cached_lease_break(struct work_struct *work);

int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
struct sdesc **sdesc);
Expand Down
8 changes: 4 additions & 4 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
}
spin_unlock(&tcon->open_file_lock);

mutex_lock(&tcon->prfid_mutex);
tcon->valid_root_fid = false;
memset(tcon->prfid, 0, sizeof(struct cifs_fid));
mutex_unlock(&tcon->prfid_mutex);
mutex_lock(&tcon->crfid.fid_mutex);
tcon->crfid.is_valid = false;
memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
mutex_unlock(&tcon->crfid.fid_mutex);

/*
* BB Add call to invalidate_inodes(sb) for all superblocks mounted
Expand Down
8 changes: 4 additions & 4 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@
#include "smb2proto.h"
#include "smbdirect.h"

#define CIFS_PORT 445
#define RFC1001_PORT 139

extern mempool_t *cifs_req_poolp;
extern bool disable_legacy_dialects;

Expand Down Expand Up @@ -3029,8 +3026,11 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)

#ifdef CONFIG_CIFS_SMB311
if ((volume_info->linux_ext) && (ses->server->posix_ext_supported)) {
if (ses->server->vals->protocol_id == SMB311_PROT_ID)
if (ses->server->vals->protocol_id == SMB311_PROT_ID) {
tcon->posix_extensions = true;
printk_once(KERN_WARNING
"SMB3.11 POSIX Extensions are experimental\n");
}
}
#endif /* 311 */

Expand Down
13 changes: 11 additions & 2 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
goto mkdir_out;
}

server = tcon->ses->server;

#ifdef CONFIG_CIFS_SMB311
if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
cifs_sb);
d_drop(direntry); /* for time being always refresh inode info */
goto mkdir_out;
}
#endif /* SMB311 */

if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
Expand All @@ -1583,8 +1594,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
goto mkdir_out;
}

server = tcon->ses->server;

if (!server->ops->mkdir) {
rc = -ENOSYS;
goto mkdir_out;
Expand Down
9 changes: 6 additions & 3 deletions fs/cifs/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ sesInfoAlloc(void)
INIT_LIST_HEAD(&ret_buf->smb_ses_list);
INIT_LIST_HEAD(&ret_buf->tcon_list);
mutex_init(&ret_buf->session_mutex);
spin_lock_init(&ret_buf->iface_lock);
}
return ret_buf;
}
Expand All @@ -102,6 +103,7 @@ sesInfoFree(struct cifs_ses *buf_to_free)
kfree(buf_to_free->user_name);
kfree(buf_to_free->domainName);
kzfree(buf_to_free->auth_key.response);
kfree(buf_to_free->iface_list);
kzfree(buf_to_free);
}

Expand All @@ -117,8 +119,9 @@ tconInfoAlloc(void)
INIT_LIST_HEAD(&ret_buf->openFileList);
INIT_LIST_HEAD(&ret_buf->tcon_list);
spin_lock_init(&ret_buf->open_file_lock);
mutex_init(&ret_buf->prfid_mutex);
ret_buf->prfid = kzalloc(sizeof(struct cifs_fid), GFP_KERNEL);
mutex_init(&ret_buf->crfid.fid_mutex);
ret_buf->crfid.fid = kzalloc(sizeof(struct cifs_fid),
GFP_KERNEL);
#ifdef CONFIG_CIFS_STATS
spin_lock_init(&ret_buf->stat_lock);
#endif
Expand All @@ -136,7 +139,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free)
atomic_dec(&tconInfoAllocCount);
kfree(buf_to_free->nativeFileSystem);
kzfree(buf_to_free->password);
kfree(buf_to_free->prfid);
kfree(buf_to_free->crfid.fid);
kfree(buf_to_free);
}

Expand Down
Loading

0 comments on commit 9ffc59d

Please sign in to comment.