Commit 797b9e5a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS updates from Steve French:
 "This patchset is the final section of the SMB2.1 support merge for
  cifs.ko.  It also includes improvements to the cifs socket handling
  from Jeff, and also fixes a few cifs bug fixes.  It adds SMB2 support
  for file and inode operations as well as moves some existing cifs code
  to use ops server struct of protocol specific callbacks.

  Most of this code is SMB2 specific.  When enabled SMB2.1 does pass
  various functional tests including most of the connectathon test
  suite, For SMB2.1, Connectathon test 4 and some related tests fail due
  to not updating mode bits remotely (cifsacl support where mode bits
  are approximated with the cifs acl is not enable for smb2), and test8
  (symlink) support is not completed for SMB2 yet (note that we will
  likely have a "Unix Extensions" eventually, at least for Samba, so in
  the long run posix locks won't have to be emulated when mounting Linux
  to Linux, but for most NAS and for Windows mounts posix lock emulation
  will still used for SMB2 in a similar fashion as we do for cifs).

  SMB2.1 dialect is supported.  Although additional fixes to enable smb2
  (the original smb2.02) dialect and to add various optional features of
  the smb3 dialect are expected to be added in the future as testing
  progresses, currently mounting with the "vers=2.1" is supported (in
  order to mount using SMB2.1 to servers like Samba 4, and Windows 7,
  Windows 2008R2)."

* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6: (82 commits)
  [CIFS] Fix indentation of fs/cifs/Kconfig entries
  [CIFS] Fix SMB2 negotiation support to select only one dialect (based on vers=)
  cifs: obtain file access during backup intent lookup (resend)
  CIFS: Fix possible freed pointer dereference in CIFS_SessSetup
  CIFS: Fix possible freed pointer dereference in SMB2_sess_setup
  CIFS: Make ops->close return void
  cifs: change DOS/NT/POSIX mapping of ERRnoresource
  cifs: remove support for deprecated "forcedirectio" and "strictcache" mount options
  cifs: remove support for CIFS_IOC_CHECKUMOUNT ioctl
  CIFS: Fix possible memory leaks in SMB2 code
  CIFS: Fix endian conversion of IndexNumber
  Trivial endian fixes
  MARK SMB2 support EXPERIMENTAL
  Update cifs version number
  cifs: add FL_CLOSE to fl_flags mask in cifs_read_flock
  cifs: Mangle string used for unc in /proc/mounts
  cifs: cleanups for cifs_mkdir_qinfo
  CIFS: Fix fast lease break after open problem
  CIFS: Add SMB2.1 lease break support
  CIFS: Fix cache coherency for read oplock case
  ...
parents 9c0ece06 1d4ab907
......@@ -9,13 +9,14 @@ config CIFS
select CRYPTO_ARC4
select CRYPTO_ECB
select CRYPTO_DES
select CRYPTO_SHA256
help
This is the client VFS module for the Common Internet File System
(CIFS) protocol which is the successor to the Server Message Block
(SMB) protocol, the native file sharing mechanism for most early
PC operating systems. The CIFS protocol is fully supported by
file servers such as Windows 2000 (including Windows 2003, NT 4
and Windows XP) as well by Samba (which provides excellent CIFS
file servers such as Windows 2000 (including Windows 2003, Windows 2008,
NT 4 and Windows XP) as well by Samba (which provides excellent CIFS
server support for Linux and many other operating systems). Limited
support for OS/2 and Windows ME and similar servers is provided as
well.
......@@ -114,6 +115,13 @@ config CIFS_POSIX
(such as Samba 3.10 and later) which can negotiate
CIFS POSIX ACL support. If unsure, say N.
config CIFS_ACL
bool "Provide CIFS ACL support"
depends on CIFS_XATTR && KEYS
help
Allows fetching CIFS/NTFS ACL from the server. The DACL blob
is handed over to the application/caller.
config CIFS_DEBUG2
bool "Enable additional CIFS debugging routines"
depends on CIFS
......@@ -138,21 +146,6 @@ config CIFS_DFS_UPCALL
IP addresses) which is needed for implicit mounts of DFS junction
points. If unsure, say N.
config CIFS_FSCACHE
bool "Provide CIFS client caching support"
depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
help
Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
to be cached locally on disk through the general filesystem cache
manager. If unsure, say N.
config CIFS_ACL
bool "Provide CIFS ACL support"
depends on CIFS_XATTR && KEYS
help
Allows to fetch CIFS/NTFS ACL from the server. The DACL blob
is handed over to the application/caller.
config CIFS_NFSD_EXPORT
bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)"
depends on CIFS && EXPERIMENTAL && BROKEN
......@@ -161,7 +154,7 @@ config CIFS_NFSD_EXPORT
config CIFS_SMB2
bool "SMB2 network file system support (EXPERIMENTAL)"
depends on EXPERIMENTAL && INET && BROKEN
depends on CIFS && EXPERIMENTAL && INET
select NLS
select KEYS
select FSCACHE
......@@ -178,3 +171,12 @@ config CIFS_SMB2
(compared to cifs) due to protocol improvements.
Unless you are a developer or tester, say N.
config CIFS_FSCACHE
bool "Provide CIFS client caching support"
depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
help
Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
to be cached locally on disk through the general filesystem cache
manager. If unsure, say N.
......@@ -17,4 +17,4 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o \
smb2misc.o smb2pdu.o smb2inode.o
smb2misc.o smb2pdu.o smb2inode.o smb2file.o
......@@ -1222,7 +1222,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
if (!open_file)
return get_cifs_acl_by_path(cifs_sb, path, pacllen);
pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
cifsFileInfo_put(open_file);
return pntsd;
}
......
......@@ -29,6 +29,7 @@
#include "ntlmssp.h"
#include <linux/ctype.h>
#include <linux/random.h>
#include <linux/highmem.h>
/*
* Calculate and return the CIFS signature based on the mac key and SMB PDU.
......@@ -37,11 +38,13 @@
* the sequence number before this function is called. Also, this function
* should be called with the server->srv_mutex held.
*/
static int cifs_calc_signature(const struct kvec *iov, int n_vec,
static int cifs_calc_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server, char *signature)
{
int i;
int rc;
struct kvec *iov = rqst->rq_iov;
int n_vec = rqst->rq_nvec;
if (iov == NULL || signature == NULL || server == NULL)
return -EINVAL;
......@@ -91,6 +94,16 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
}
}
/* now hash over the rq_pages array */
for (i = 0; i < rqst->rq_npages; i++) {
struct kvec p_iov;
cifs_rqst_page_to_kvec(rqst, i, &p_iov);
crypto_shash_update(&server->secmech.sdescmd5->shash,
p_iov.iov_base, p_iov.iov_len);
kunmap(rqst->rq_pages[i]);
}
rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
if (rc)
cERROR(1, "%s: Could not generate md5 hash", __func__);
......@@ -99,12 +112,12 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
}
/* must be called with server->srv_mutex held */
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number)
{
int rc = 0;
char smb_signature[20];
struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
if ((cifs_pdu == NULL) || (server == NULL))
return -EINVAL;
......@@ -125,7 +138,7 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
*pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++;
rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
rc = cifs_calc_signature(rqst, server, smb_signature);
if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else
......@@ -134,6 +147,15 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
return rc;
}
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence)
{
struct smb_rqst rqst = { .rq_iov = iov,
.rq_nvec = n_vec };
return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
}
/* must be called with server->srv_mutex held */
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number)
......@@ -147,14 +169,14 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
pexpected_response_sequence_number);
}
int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
int cifs_verify_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server,
__u32 expected_sequence_number)
{
unsigned int rc;
char server_response_sig[8];
char what_we_think_sig_should_be[20];
struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
if (cifs_pdu == NULL || server == NULL)
return -EINVAL;
......@@ -186,8 +208,7 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
cifs_pdu->Signature.Sequence.Reserved = 0;
mutex_lock(&server->srv_mutex);
rc = cifs_calc_signature(iov, nr_iov, server,
what_we_think_sig_should_be);
rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
mutex_unlock(&server->srv_mutex);
if (rc)
......@@ -686,12 +707,17 @@ calc_seckey(struct cifs_ses *ses)
void
cifs_crypto_shash_release(struct TCP_Server_Info *server)
{
if (server->secmech.hmacsha256)
crypto_free_shash(server->secmech.hmacsha256);
if (server->secmech.md5)
crypto_free_shash(server->secmech.md5);
if (server->secmech.hmacmd5)
crypto_free_shash(server->secmech.hmacmd5);
kfree(server->secmech.sdeschmacsha256);
kfree(server->secmech.sdeschmacmd5);
kfree(server->secmech.sdescmd5);
......@@ -716,6 +742,13 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
goto crypto_allocate_md5_fail;
}
server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
if (IS_ERR(server->secmech.hmacsha256)) {
cERROR(1, "could not allocate crypto hmacsha256\n");
rc = PTR_ERR(server->secmech.hmacsha256);
goto crypto_allocate_hmacsha256_fail;
}
size = sizeof(struct shash_desc) +
crypto_shash_descsize(server->secmech.hmacmd5);
server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
......@@ -727,7 +760,6 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
server->secmech.sdeschmacmd5->shash.flags = 0x0;
size = sizeof(struct shash_desc) +
crypto_shash_descsize(server->secmech.md5);
server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
......@@ -739,12 +771,29 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
server->secmech.sdescmd5->shash.flags = 0x0;
size = sizeof(struct shash_desc) +
crypto_shash_descsize(server->secmech.hmacsha256);
server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
if (!server->secmech.sdeschmacsha256) {
cERROR(1, "%s: Can't alloc hmacsha256\n", __func__);
rc = -ENOMEM;
goto crypto_allocate_hmacsha256_sdesc_fail;
}
server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
server->secmech.sdeschmacsha256->shash.flags = 0x0;
return 0;
crypto_allocate_hmacsha256_sdesc_fail:
kfree(server->secmech.sdescmd5);
crypto_allocate_md5_sdesc_fail:
kfree(server->secmech.sdeschmacmd5);
crypto_allocate_hmacmd5_sdesc_fail:
crypto_free_shash(server->secmech.hmacsha256);
crypto_allocate_hmacsha256_fail:
crypto_free_shash(server->secmech.md5);
crypto_allocate_md5_fail:
......
......@@ -36,6 +36,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/namei.h>
#include <linux/random.h>
#include <net/ipv6.h>
#include "cifsfs.h"
#include "cifspdu.h"
......@@ -51,7 +52,6 @@
#ifdef CONFIG_CIFS_SMB2
#include "smb2pdu.h"
#endif
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
int cifsFYI = 0;
int cifsERROR = 1;
......@@ -89,6 +89,10 @@ extern mempool_t *cifs_mid_poolp;
struct workqueue_struct *cifsiod_wq;
#ifdef CONFIG_CIFS_SMB2
__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
#endif
static int
cifs_read_super(struct super_block *sb)
{
......@@ -160,13 +164,12 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
struct super_block *sb = dentry->d_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
int rc = -EOPNOTSUPP;
struct TCP_Server_Info *server = tcon->ses->server;
unsigned int xid;
int rc = 0;
xid = get_xid();
buf->f_type = CIFS_MAGIC_NUMBER;
/*
* PATH_MAX may be too long - it would presumably be total path,
* but note that some servers (includinng Samba 3) have a shorter
......@@ -178,27 +181,8 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_files = 0; /* undefined */
buf->f_ffree = 0; /* unlimited */
/*
* We could add a second check for a QFS Unix capability bit
*/
if ((tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);
/*
* Only need to call the old QFSInfo if failed on newer one,
* e.g. by OS/2.
**/
if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
rc = CIFSSMBQFSInfo(xid, tcon, buf);
/*
* Some old Windows servers also do not support level 103, retry with
* older level one if old server failed the previous call or we
* bypassed it because we detected that this was an older LANMAN sess
*/
if (rc)
rc = SMBOldQFSInfo(xid, tcon, buf);
if (server->ops->queryfs)
rc = server->ops->queryfs(xid, tcon, buf);
free_xid(xid);
return 0;
......@@ -239,9 +223,10 @@ cifs_alloc_inode(struct super_block *sb)
return NULL;
cifs_inode->cifsAttrs = 0x20; /* default */
cifs_inode->time = 0;
/* Until the file is open and we have gotten oplock
info back from the server, can not assume caching of
file data or metadata */
/*
* Until the file is open and we have gotten oplock info back from the
* server, can not assume caching of file data or metadata.
*/
cifs_set_oplock_level(cifs_inode, 0);
cifs_inode->delete_pending = false;
cifs_inode->invalid_mapping = false;
......@@ -249,11 +234,16 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->server_eof = 0;
cifs_inode->uniqueid = 0;
cifs_inode->createtime = 0;
/* Can not set i_flags here - they get immediately overwritten
to zero by the VFS */
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
#ifdef CONFIG_CIFS_SMB2
get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE);
#endif
/*
* Can not set i_flags here - they get immediately overwritten to zero
* by the VFS.
*/
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; */
INIT_LIST_HEAD(&cifs_inode->openFileList);
INIT_LIST_HEAD(&cifs_inode->llist);
return &cifs_inode->vfs_inode;
}
......@@ -360,7 +350,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
cifs_show_security(s, tcon->ses->server);
cifs_show_cache_flavor(s, cifs_sb);
seq_printf(s, ",unc=%s", tcon->treeName);
seq_printf(s, ",unc=");
seq_escape(s, tcon->treeName, " \t\n\\");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
seq_printf(s, ",multiuser");
......@@ -957,7 +948,7 @@ cifs_init_once(void *inode)
struct cifsInodeInfo *cifsi = inode;
inode_init_once(&cifsi->vfs_inode);
mutex_init(&cifsi->lock_mutex);
init_rwsem(&cifsi->lock_sem);
}
static int
......@@ -1127,6 +1118,10 @@ init_cifs(void)
spin_lock_init(&cifs_file_list_lock);
spin_lock_init(&GlobalMid_Lock);
#ifdef CONFIG_CIFS_SMB2
get_random_bytes(cifs_client_guid, SMB2_CLIENT_GUID_SIZE);
#endif
if (cifs_max_pending < 2) {
cifs_max_pending = 2;
cFYI(1, "cifs_max_pending set to min of 2");
......
......@@ -128,5 +128,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "1.78"
#define CIFS_VERSION "2.0"
#endif /* _CIFSFS_H */
This diff is collapsed.
......@@ -2210,7 +2210,7 @@ typedef struct { /* data block encoding of response to level 263 QPathInfo */
__u8 DeletePending;
__u8 Directory;
__u16 Pad2;
__u64 IndexNumber;
__le64 IndexNumber;
__le32 EASize;
__le32 AccessFlags;
__u64 IndexNumber1;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -160,17 +160,18 @@ check_name(struct dentry *direntry)
static int
cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
struct tcon_link *tlink, unsigned oflags, umode_t mode,
__u32 *oplock, __u16 *fileHandle, int *created)
__u32 *oplock, struct cifs_fid *fid, int *created)
{
int rc = -ENOENT;
int create_options = CREATE_NOT_DIR;
int desiredAccess;
int desired_access;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_tcon *tcon = tlink_tcon(tlink);
char *full_path = NULL;
FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL;
int disposition;
struct TCP_Server_Info *server = tcon->ses->server;
*oplock = 0;
if (tcon->ses->server->oplocks)
......@@ -185,8 +186,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = cifs_posix_open(full_path, &newinode,
inode->i_sb, mode, oflags, oplock, fileHandle, xid);
rc = cifs_posix_open(full_path, &newinode, inode->i_sb, mode,
oflags, oplock, &fid->netfid, xid);
switch (rc) {
case 0:
if (newinode == NULL) {
......@@ -202,7 +203,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
* close it and proceed as if it were a normal
* lookup.
*/
CIFSSMBClose(xid, tcon, *fileHandle);
CIFSSMBClose(xid, tcon, fid->netfid);
goto cifs_create_get_file_info;
}
/* success, no need to query */
......@@ -244,11 +245,11 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
*/
}
desiredAccess = 0;
desired_access = 0;
if (OPEN_FMODE(oflags) & FMODE_READ)
desiredAccess |= GENERIC_READ; /* is this too little? */
desired_access |= GENERIC_READ; /* is this too little? */
if (OPEN_FMODE(oflags) & FMODE_WRITE)
desiredAccess |= GENERIC_WRITE;
desired_access |= GENERIC_WRITE;
disposition = FILE_OVERWRITE_IF;
if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
......@@ -260,8 +261,15 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
else
cFYI(1, "Create flag not set in create function");
/* BB add processing to set equivalent of mode - e.g. via CreateX with
ACLs */
/*
* BB add processing to set equivalent of mode - e.g. via CreateX with
* ACLs
*/
if (!server->ops->open) {
rc = -ENOSYS;
goto out;
}
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) {
......@@ -279,28 +287,18 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT;
if (tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options,
fileHandle, oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
else
rc = -EIO; /* no NT SMB support fall into legacy open below */
if (rc == -EIO) {
/* old server, retry the open legacy style */
rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options,
fileHandle, oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
}
rc = server->ops->open(xid, tcon, full_path, disposition,
desired_access, create_options, fid, oplock,
buf, cifs_sb);
if (rc) {
cFYI(1, "cifs_create returned 0x%x", rc);
goto out;
}
/* If Open reported that we actually created a file
then we now have to set the mode if possible */
/*
* If Open reported that we actually created a file then we now have to
* set the mode if possible.
*/
if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
struct cifs_unix_set_info_args args = {
.mode = mode,
......@@ -321,11 +319,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
}
CIFSSMBUnixSetFileInfo(xid, tcon, &args, *fileHandle,
current->tgid);
CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
current->tgid);
} else {
/* BB implement mode setting via Windows security
descriptors e.g. */
/*
* BB implement mode setting via Windows security
* descriptors e.g.
*/
/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
/* Could set r/o dos attribute if mode & 0222 == 0 */
......@@ -334,12 +334,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
cifs_create_get_file_info:
/* server might mask mode so we have to query for it */
if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid);
rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
xid);
else {
rc = cifs_get_inode_info(&newinode, full_path, buf,
inode->i_sb, xid, fileHandle);
rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
xid, &fid->netfid);
if (newinode) {
if (server->ops->set_lease_key)
server->ops->set_lease_key(newinode, fid);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
newinode->i_mode = mode;
if ((*oplock & CIFS_CREATE_ACTION) &&
......@@ -356,7 +358,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
cifs_create_set_dentry:
if (rc != 0) {
cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
CIFSSMBClose(xid, tcon, *fileHandle);
if (server->ops->close)
server->ops->close(xid, tcon, fid);
goto out;
}
d_drop(direntry);
......@@ -377,11 +380,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
unsigned int xid;
struct tcon_link *tlink;
struct cifs_tcon *tcon;
__u16 fileHandle;
struct TCP_Server_Info *server;
struct cifs_fid fid;
struct cifs_pending_open open;
__u32 oplock;
struct cifsFileInfo *pfile_info;
struct cifsFileInfo *file_info;
/* Posix open is only called (at lookup time) for file create now. For
/*
* Posix open is only called (at lookup time) for file create now. For
* opens (rather than creates), because we do not know if it is a file
* or directory yet, and current Samba no longer allows us to do posix
* open on dirs, we could end up wasting an open call on what turns out
......@@ -413,22 +419,34 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
goto out_free_xid;
tcon = tlink_tcon(tlink);
server = tcon->ses->server;
if (server->ops->new_lease_key)
server->ops->new_lease_key(&fid);
cifs_add_pending_open(&fid, tlink, &open);
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
&oplock, &fileHandle, opened);
&oplock, &fid, opened);
if (rc)
if (rc) {
cifs_del_pending_open(&open);
goto out;
}
rc = finish_open(file, direntry, generic_file_open, opened);
if (rc) {
CIFSSMBClose(xid, tcon, fileHandle);
if (server->ops->close)
server->ops->close(xid, tcon, &fid);
cifs_del_pending_open(&open);
goto out;
}
pfile_info = cifs_new_fileinfo(fileHandle, file, tlink, oplock);
if (pfile_info == NULL) {
CIFSSMBClose(xid, tcon, fileHandle);
file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
if (file_info == NULL) {
if (server->ops->close)
server->ops->close(xid, tcon, &fid);
cifs_del_pending_open(&open);
rc = -ENOMEM;
}
......@@ -453,7 +471,9 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
*/
unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
struct tcon_link *tlink;
__u16 fileHandle;
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
struct cifs_fid fid;
__u32 oplock;
int created = FILE_CREATED;
......@@ -465,10 +485,16 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
if (IS_ERR(tlink))
goto out_free_xid;
tcon = tlink_tcon(tlink);
server = tcon->ses->server;
if (server->ops->new_lease_key)
server->ops->new_lease_key(&fid);
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
&oplock, &fileHandle, &created);
if (!rc)
CIFSSMBClose(xid, tlink_tcon(tlink), fileHandle);
&oplock, &fid, &created);
if (!rc && server->ops->close)
server->ops->close(xid, tcon, &fid);
cifs_put_tlink(tlink);
out_free_xid:
......
This diff is collapsed.
This diff is collapsed.
......@@ -28,8 +28,6 @@
#include "cifs_debug.h"
#include "cifsfs.h"
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
{
struct inode *inode = filep->f_dentry->d_inode;
......@@ -51,23 +49,6 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
cifs_sb = CIFS_SB(inode->i_sb);
switch (command) {
static bool warned = false;
case CIFS_IOC_CHECKUMOUNT:
if (!warned) {
warned = true;
cERROR(1, "the CIFS_IOC_CHECKMOUNT ioctl will "
"be deprecated in 3.7. Please "
"migrate away from the use of "
"umount.cifs");
}
cFYI(1, "User unmount attempted");
if (cifs_sb->mnt_uid == current_uid())
rc = 0;
else {
rc = -EACCES;
cFYI(1, "uids do not match");
}
break;
#ifdef CONFIG_CIFS_POSIX
case FS_IOC_GETFLAGS:
if (pSMBFile == NULL)
......@@ -75,8 +56,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
tcon = tlink_tcon(pSMBFile->tlink);
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
if (CIFS_UNIX_EXTATTR_CAP & caps) {
rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
&ExtAttrBits, &ExtAttrMask);
rc = CIFSGetExtAttr(xid, tcon,
pSMBFile->fid.netfid,
&ExtAttrBits, &ExtAttrMask);
if (rc == 0)
rc = put_user(ExtAttrBits &
FS_FL_USER_VISIBLE,
......@@ -94,8 +76,12 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
rc = -EFAULT;
break;
}
/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
extAttrBits, &ExtAttrMask);*/
/*
* rc = CIFSGetExtAttr(xid, tcon,
* pSMBFile->fid.netfid,
* extAttrBits,
* &ExtAttrMask);
*/
}
cFYI(1, "set flags not implemented yet");
break;
......
This diff is collapsed.
......@@ -466,7 +466,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
list_for_each(tmp2, &tcon->openFileList) {
netfile = list_entry(tmp2, struct cifsFileInfo,
tlist);
if (pSMB->Fid != netfile->netfid)
if (pSMB->Fid != netfile->fid.netfid)
continue;
cFYI(1, "file id match, oplock break");
......@@ -579,3 +579,33 @@ backup_cred(struct cifs_sb_info *cifs_sb)
return false;
}
void
cifs_del_pending_open(struct cifs_pending_open *open)
{
spin_lock(&cifs_file_list_lock);
list_del(&open->olist);
spin_unlock(&cifs_file_list_lock);
}
void
cifs_add_pending_open_locked(struct cifs_fid *fid, struct tcon_link *tlink,
struct cifs_pending_open *open)
{
#ifdef CONFIG_CIFS_SMB2
memcpy(open->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
#endif
open->oplock = CIFS_OPLOCK_NO_CHANGE;
open->tlink = tlink;
fid->pending_open = open;
list_add_tail(&open->olist, &tlink_tcon(tlink)->pending_opens);
}
void
cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
struct cifs_pending_open *open)
{
spin_lock(&cifs_file_list_lock);
cifs_add_pending_open_locked(fid, tlink, open);
spin_unlock(&cifs_file_list_lock);
}
......@@ -110,7 +110,7 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
{ERRnoroom, -ENOSPC},
{ERRrmuns, -EUSERS},
{ERRtimeout, -ETIME},
{ERRnoresource, -ENOBUFS},
{ERRnoresource, -EREMOTEIO},
{ERRtoomanyuids, -EUSERS},
{ERRbaduid, -EACCES},
{ERRusempx, -EIO},
......@@ -412,7 +412,7 @@ static const struct {
from NT_STATUS_INSUFFICIENT_RESOURCES to
NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */
{
ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
ERRDOS, ERRnoresource, NT_STATUS_INSUFFICIENT_RESOURCES}, {
ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
......@@ -682,7 +682,7 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
ERRDOS, ERRnoresource, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
......@@ -913,8 +913,9 @@ map_smb_to_linux_error(char *buf, bool logErr)
* portion, the number of word parameters and the data portion of the message
*/
unsigned int
smbCalcSize(struct smb_hdr *ptr)
smbCalcSize(void *buf)
{
struct smb_hdr *ptr = (struct smb_hdr *)buf;
return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
2 /* size of the bcc field */ + get_bcc(ptr));
}
......
This diff is collapsed.
......@@ -876,7 +876,8 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
smb_buf = (struct smb_hdr *)iov[0].iov_base;
if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError ==
if ((type == RawNTLMSSP) && (resp_buf_type != CIFS_NO_BUFFER) &&
(smb_buf->Status.CifsError ==
cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
if (phase != NtLmNegotiate) {
cERROR(1, "Unexpected more processing error");
......
This diff is collapsed.
This diff is collapsed.
......@@ -23,6 +23,8 @@
#ifndef _SMB2_GLOB_H
#define _SMB2_GLOB_H
#define SMB2_MAGIC_NUMBER 0xFE534D42
/*
*****************************************************************
* Constants go here
......@@ -40,5 +42,17 @@
#define SMB2_OP_MKDIR 5
#define SMB2_OP_RENAME 6
#define SMB2_OP_DELETE 7
#define SMB2_OP_HARDLINK 8
#define SMB2_OP_SET_EOF 9
/* Used when constructing chained read requests. */
#define CHAINED_REQUEST 1
#define START_OF_CHAIN 2
#define END_OF_CHAIN 4
#define RELATED_REQUEST 8
#define SMB2_SIGNATURE_SIZE (16)
#define SMB2_NTLMV2_SESSKEY_SIZE (16)
#define SMB2_HMACSHA256_SIZE (32)
#endif /* _SMB2_GLOB_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment