mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
This commit is contained in:
commit
0f36b018b2
21 changed files with 729 additions and 183 deletions
|
@ -1,3 +1,11 @@
|
|||
Version 1.40
|
||||
------------
|
||||
Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
|
||||
of readpages by eliminating one extra memcpy. Allow update of file size
|
||||
from remote server even if file is open for write as long as mount is
|
||||
directio. Recognize share mode security and send NTLM encrypted password
|
||||
on tree connect if share mode negotiated.
|
||||
|
||||
Version 1.39
|
||||
------------
|
||||
Defer close of a file handle slightly if pending writes depend on that handle
|
||||
|
@ -7,6 +15,8 @@ Fix SFU style symlinks and mknod needed for servers which do not support the
|
|||
CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative
|
||||
dentries so files that the client sees as deleted but that later get created
|
||||
on the server will be recognized. Add client side permission check on setattr.
|
||||
Timeout stuck requests better (where server has never responded or sent corrupt
|
||||
responses)
|
||||
|
||||
Version 1.38
|
||||
------------
|
||||
|
|
|
@ -436,6 +436,16 @@ A partial list of the supported mount options follows:
|
|||
SFU does). In the future the bottom 9 bits of the mode
|
||||
mode also will be emulated using queries of the security
|
||||
descriptor (ACL).
|
||||
sec Security mode. Allowed values are:
|
||||
none attempt to connection as a null user (no name)
|
||||
krb5 Use Kerberos version 5 authentication
|
||||
krb5i Use Kerberos authentication and packet signing
|
||||
ntlm Use NTLM password hashing (default)
|
||||
ntlmi Use NTLM password hashing with signing (if
|
||||
/proc/fs/cifs/PacketSigningEnabled on or if
|
||||
server requires signing also can be the default)
|
||||
ntlmv2 Use NTLMv2 password hashing
|
||||
ntlmv2i Use NTLMv2 password hashing with packet signing
|
||||
|
||||
The mount.cifs mount helper also accepts a few mount options before -o
|
||||
including:
|
||||
|
|
|
@ -219,6 +219,10 @@ cifs_stats_write(struct file *file, const char __user *buffer,
|
|||
|
||||
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_set(&totBufAllocCount, 0);
|
||||
atomic_set(&totSmBufAllocCount, 0);
|
||||
#endif /* CONFIG_CIFS_STATS2 */
|
||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
||||
tcon = list_entry(tmp, struct cifsTconInfo,
|
||||
cifsConnectionList);
|
||||
|
@ -276,6 +280,14 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
|||
smBufAllocCount.counter,cifs_min_small);
|
||||
length += item_length;
|
||||
buf += item_length;
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
|
||||
atomic_read(&totBufAllocCount),
|
||||
atomic_read(&totSmBufAllocCount));
|
||||
length += item_length;
|
||||
buf += item_length;
|
||||
#endif /* CONFIG_CIFS_STATS2 */
|
||||
|
||||
item_length =
|
||||
sprintf(buf,"Operations (MIDs): %d\n",
|
||||
midCount.counter);
|
||||
|
@ -389,8 +401,8 @@ static read_proc_t ntlmv2_enabled_read;
|
|||
static write_proc_t ntlmv2_enabled_write;
|
||||
static read_proc_t packet_signing_enabled_read;
|
||||
static write_proc_t packet_signing_enabled_write;
|
||||
static read_proc_t quotaEnabled_read;
|
||||
static write_proc_t quotaEnabled_write;
|
||||
static read_proc_t experimEnabled_read;
|
||||
static write_proc_t experimEnabled_write;
|
||||
static read_proc_t linuxExtensionsEnabled_read;
|
||||
static write_proc_t linuxExtensionsEnabled_write;
|
||||
|
||||
|
@ -430,9 +442,9 @@ cifs_proc_init(void)
|
|||
pde->write_proc = oplockEnabled_write;
|
||||
|
||||
pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
|
||||
quotaEnabled_read, NULL);
|
||||
experimEnabled_read, NULL);
|
||||
if (pde)
|
||||
pde->write_proc = quotaEnabled_write;
|
||||
pde->write_proc = experimEnabled_write;
|
||||
|
||||
pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
|
||||
linuxExtensionsEnabled_read, NULL);
|
||||
|
@ -574,14 +586,13 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
|
|||
}
|
||||
|
||||
static int
|
||||
quotaEnabled_read(char *page, char **start, off_t off,
|
||||
experimEnabled_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = sprintf(page, "%d\n", experimEnabled);
|
||||
/* could also check if quotas are enabled in kernel
|
||||
as a whole first */
|
||||
|
||||
len -= off;
|
||||
*start = page + off;
|
||||
|
||||
|
@ -596,7 +607,7 @@ quotaEnabled_read(char *page, char **start, off_t off,
|
|||
return len;
|
||||
}
|
||||
static int
|
||||
quotaEnabled_write(struct file *file, const char __user *buffer,
|
||||
experimEnabled_write(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
char c;
|
||||
|
@ -609,6 +620,8 @@ quotaEnabled_write(struct file *file, const char __user *buffer,
|
|||
experimEnabled = 0;
|
||||
else if (c == '1' || c == 'y' || c == 'Y')
|
||||
experimEnabled = 1;
|
||||
else if (c == '2')
|
||||
experimEnabled = 2;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -620,8 +633,6 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
|
|||
int len;
|
||||
|
||||
len = sprintf(page, "%d\n", linuxExtEnabled);
|
||||
/* could also check if quotas are enabled in kernel
|
||||
as a whole first */
|
||||
len -= off;
|
||||
*start = page + off;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
|
||||
#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
|
||||
#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
|
||||
#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
|
||||
|
||||
struct cifs_sb_info {
|
||||
struct cifsTconInfo *tcon; /* primary mount */
|
||||
|
|
38
fs/cifs/cifsacl.h
Normal file
38
fs/cifs/cifsacl.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* fs/cifs/cifsacl.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2005
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _CIFSACL_H
|
||||
#define _CIFSACL_H
|
||||
|
||||
struct cifs_sid {
|
||||
__u8 revision; /* revision level */
|
||||
__u8 num_subauths;
|
||||
__u8 authority[6];
|
||||
__u32 sub_auth[4];
|
||||
/* next sub_auth if any ... */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* everyone */
|
||||
extern const struct cifs_sid sid_everyone;
|
||||
/* group users */
|
||||
extern const struct cifs_sid sid_user;
|
||||
|
||||
#endif /* _CIFSACL_H */
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* fs/cifs/cifsencrypt.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2003
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -82,6 +82,59 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
|
||||
const char * key, char * signature)
|
||||
{
|
||||
struct MD5Context context;
|
||||
|
||||
if((iov == NULL) || (signature == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
MD5Init(&context);
|
||||
MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
|
||||
|
||||
/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
|
||||
|
||||
MD5Final(signature,&context);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
/* return 0; */
|
||||
}
|
||||
|
||||
|
||||
int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
|
||||
__u32 * pexpected_response_sequence_number)
|
||||
{
|
||||
int rc = 0;
|
||||
char smb_signature[20];
|
||||
struct smb_hdr * cifs_pdu = iov[0].iov_base;
|
||||
|
||||
if((cifs_pdu == NULL) || (server == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
||||
return rc;
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||
cpu_to_le32(server->sequence_number);
|
||||
cifs_pdu->Signature.Sequence.Reserved = 0;
|
||||
|
||||
*pexpected_response_sequence_number = server->sequence_number++;
|
||||
server->sequence_number++;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
|
||||
rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
|
||||
smb_signature);
|
||||
if(rc)
|
||||
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
||||
else
|
||||
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
|
||||
__u32 expected_sequence_number)
|
||||
{
|
||||
|
|
|
@ -513,6 +513,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
|
|||
return written;
|
||||
}
|
||||
|
||||
static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
|
||||
{
|
||||
/* origin == SEEK_END => we must revalidate the cached file length */
|
||||
if (origin == 2) {
|
||||
int retval = cifs_revalidate(file->f_dentry);
|
||||
if (retval < 0)
|
||||
return (loff_t)retval;
|
||||
}
|
||||
return remote_llseek(file, offset, origin);
|
||||
}
|
||||
|
||||
static struct file_system_type cifs_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "cifs",
|
||||
|
@ -586,6 +597,7 @@ struct file_operations cifs_file_ops = {
|
|||
.flush = cifs_flush,
|
||||
.mmap = cifs_file_mmap,
|
||||
.sendfile = generic_file_sendfile,
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
@ -609,7 +621,7 @@ struct file_operations cifs_file_direct_ops = {
|
|||
#ifdef CONFIG_CIFS_POSIX
|
||||
.ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.dir_notify = cifs_dir_notify,
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
|
@ -627,6 +639,7 @@ struct file_operations cifs_file_nobrl_ops = {
|
|||
.flush = cifs_flush,
|
||||
.mmap = cifs_file_mmap,
|
||||
.sendfile = generic_file_sendfile,
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
@ -649,7 +662,7 @@ struct file_operations cifs_file_direct_nobrl_ops = {
|
|||
#ifdef CONFIG_CIFS_POSIX
|
||||
.ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
.llseek = cifs_llseek,
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.dir_notify = cifs_dir_notify,
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
|
@ -733,7 +746,7 @@ cifs_init_request_bufs(void)
|
|||
kmem_cache_destroy(cifs_req_cachep);
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
|
||||
/* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
|
||||
almost all handle based requests (but not write response, nor is it
|
||||
sufficient for path based requests). A smaller size would have
|
||||
been more efficient (compacting multiple slab items on one 4k page)
|
||||
|
@ -742,7 +755,8 @@ cifs_init_request_bufs(void)
|
|||
efficient to alloc 1 per page off the slab compared to 17K (5page)
|
||||
alloc of large cifs buffers even when page debugging is on */
|
||||
cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
|
||||
MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
|
||||
MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
|
||||
NULL, NULL);
|
||||
if (cifs_sm_req_cachep == NULL) {
|
||||
mempool_destroy(cifs_req_poolp);
|
||||
kmem_cache_destroy(cifs_req_cachep);
|
||||
|
@ -954,6 +968,12 @@ init_cifs(void)
|
|||
atomic_set(&tconInfoReconnectCount, 0);
|
||||
|
||||
atomic_set(&bufAllocCount, 0);
|
||||
atomic_set(&smBufAllocCount, 0);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_set(&totBufAllocCount, 0);
|
||||
atomic_set(&totSmBufAllocCount, 0);
|
||||
#endif /* CONFIG_CIFS_STATS2 */
|
||||
|
||||
atomic_set(&midCount, 0);
|
||||
GlobalCurrentXid = 0;
|
||||
GlobalTotalActiveXid = 0;
|
||||
|
|
|
@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
|||
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
||||
extern int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||
unsigned int command, unsigned long arg);
|
||||
#define CIFS_VERSION "1.39"
|
||||
#define CIFS_VERSION "1.40"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
|
|
@ -233,6 +233,8 @@ struct cifsTconInfo {
|
|||
atomic_t num_hardlinks;
|
||||
atomic_t num_symlinks;
|
||||
atomic_t num_locks;
|
||||
atomic_t num_acl_get;
|
||||
atomic_t num_acl_set;
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
unsigned long long time_writes;
|
||||
unsigned long long time_reads;
|
||||
|
@ -285,6 +287,7 @@ struct cifs_search_info {
|
|||
unsigned endOfSearch:1;
|
||||
unsigned emptyDir:1;
|
||||
unsigned unicode:1;
|
||||
unsigned smallBuf:1; /* so we know which buf_release function to call */
|
||||
};
|
||||
|
||||
struct cifsFileInfo {
|
||||
|
@ -420,7 +423,12 @@ struct dir_notify_req {
|
|||
#define MID_RESPONSE_RECEIVED 4
|
||||
#define MID_RETRY_NEEDED 8 /* session closed while this request out */
|
||||
#define MID_NO_RESP_NEEDED 0x10
|
||||
#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */
|
||||
|
||||
/* Types of response buffer returned from SendReceive2 */
|
||||
#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
|
||||
#define CIFS_SMALL_BUFFER 1
|
||||
#define CIFS_LARGE_BUFFER 2
|
||||
#define CIFS_IOVEC 4 /* array of response buffers */
|
||||
|
||||
/*
|
||||
*****************************************************************
|
||||
|
@ -505,7 +513,11 @@ GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
|
|||
GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
|
||||
|
||||
/* Various Debug counters to remove someday (BB) */
|
||||
GLOBAL_EXTERN atomic_t bufAllocCount;
|
||||
GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */
|
||||
GLOBAL_EXTERN atomic_t totSmBufAllocCount;
|
||||
#endif
|
||||
GLOBAL_EXTERN atomic_t smBufAllocCount;
|
||||
GLOBAL_EXTERN atomic_t midCount;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* fs/cifs/cifspdu.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002
|
||||
* Copyright (c) International Business Machines Corp., 2002,2005
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -80,7 +80,11 @@
|
|||
#define NT_TRANSACT_GET_USER_QUOTA 0x07
|
||||
#define NT_TRANSACT_SET_USER_QUOTA 0x08
|
||||
|
||||
#define MAX_CIFS_HDR_SIZE 256 /* is future chained NTCreateXReadX bigger? */
|
||||
#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
|
||||
/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
|
||||
/* among the requests (NTCreateX response is bigger with wct of 34) */
|
||||
#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
|
||||
#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
|
||||
|
||||
/* internal cifs vfs structures */
|
||||
/*****************************************************************
|
||||
|
@ -524,7 +528,7 @@ typedef union smb_com_session_setup_andx {
|
|||
/* STRING PrimaryDomain */
|
||||
/* STRING NativeOS */
|
||||
/* STRING NativeLanMan */
|
||||
} __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) request format */
|
||||
} __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */
|
||||
|
||||
struct { /* default (NTLM) response format */
|
||||
struct smb_hdr hdr; /* wct = 3 */
|
||||
|
@ -536,7 +540,7 @@ typedef union smb_com_session_setup_andx {
|
|||
unsigned char NativeOS[1]; /* followed by */
|
||||
/* unsigned char * NativeLanMan; */
|
||||
/* unsigned char * PrimaryDomain; */
|
||||
} __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response format */
|
||||
} __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
|
||||
} __attribute__((packed)) SESSION_SETUP_ANDX;
|
||||
|
||||
#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
|
||||
|
@ -1003,10 +1007,49 @@ typedef struct smb_com_setattr_rsp {
|
|||
|
||||
/* empty wct response to setattr */
|
||||
|
||||
/***************************************************/
|
||||
/*******************************************************/
|
||||
/* NT Transact structure defintions follow */
|
||||
/* Currently only ioctl and notify are implemented */
|
||||
/***************************************************/
|
||||
/* Currently only ioctl, acl (get security descriptor) */
|
||||
/* and notify are implemented */
|
||||
/*******************************************************/
|
||||
typedef struct smb_com_ntransact_req {
|
||||
struct smb_hdr hdr; /* wct >= 19 */
|
||||
__u8 MaxSetupCount;
|
||||
__u16 Reserved;
|
||||
__le32 TotalParameterCount;
|
||||
__le32 TotalDataCount;
|
||||
__le32 MaxParameterCount;
|
||||
__le32 MaxDataCount;
|
||||
__le32 ParameterCount;
|
||||
__le32 ParameterOffset;
|
||||
__le32 DataCount;
|
||||
__le32 DataOffset;
|
||||
__u8 SetupCount; /* four setup words follow subcommand */
|
||||
/* SNIA spec incorrectly included spurious pad here */
|
||||
__le16 SubCommand; /* 2 = IOCTL/FSCTL */
|
||||
/* SetupCount words follow then */
|
||||
__le16 ByteCount;
|
||||
__u8 Pad[3];
|
||||
__u8 Parms[0];
|
||||
} __attribute__((packed)) NTRANSACT_REQ;
|
||||
|
||||
typedef struct smb_com_ntransact_rsp {
|
||||
struct smb_hdr hdr; /* wct = 18 */
|
||||
__u8 Reserved[3];
|
||||
__le32 TotalParameterCount;
|
||||
__le32 TotalDataCount;
|
||||
__le32 ParameterCount;
|
||||
__le32 ParameterOffset;
|
||||
__le32 ParameterDisplacement;
|
||||
__le32 DataCount;
|
||||
__le32 DataOffset;
|
||||
__le32 DataDisplacement;
|
||||
__u8 SetupCount; /* 0 */
|
||||
__u16 ByteCount;
|
||||
/* __u8 Pad[3]; */
|
||||
/* parms and data follow */
|
||||
} __attribute__((packed)) NTRANSACT_RSP;
|
||||
|
||||
typedef struct smb_com_transaction_ioctl_req {
|
||||
struct smb_hdr hdr; /* wct = 23 */
|
||||
__u8 MaxSetupCount;
|
||||
|
@ -1021,11 +1064,11 @@ typedef struct smb_com_transaction_ioctl_req {
|
|||
__le32 DataOffset;
|
||||
__u8 SetupCount; /* four setup words follow subcommand */
|
||||
/* SNIA spec incorrectly included spurious pad here */
|
||||
__le16 SubCommand;/* 2 = IOCTL/FSCTL */
|
||||
__le16 SubCommand; /* 2 = IOCTL/FSCTL */
|
||||
__le32 FunctionCode;
|
||||
__u16 Fid;
|
||||
__u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
|
||||
__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
|
||||
__u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
|
||||
__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
|
||||
__le16 ByteCount;
|
||||
__u8 Pad[3];
|
||||
__u8 Data[1];
|
||||
|
@ -1045,9 +1088,35 @@ typedef struct smb_com_transaction_ioctl_rsp {
|
|||
__u8 SetupCount; /* 1 */
|
||||
__le16 ReturnedDataLen;
|
||||
__u16 ByteCount;
|
||||
__u8 Pad[3];
|
||||
} __attribute__((packed)) TRANSACT_IOCTL_RSP;
|
||||
|
||||
#define CIFS_ACL_OWNER 1
|
||||
#define CIFS_ACL_GROUP 2
|
||||
#define CIFS_ACL_DACL 4
|
||||
#define CIFS_ACL_SACL 8
|
||||
|
||||
typedef struct smb_com_transaction_qsec_req {
|
||||
struct smb_hdr hdr; /* wct = 19 */
|
||||
__u8 MaxSetupCount;
|
||||
__u16 Reserved;
|
||||
__le32 TotalParameterCount;
|
||||
__le32 TotalDataCount;
|
||||
__le32 MaxParameterCount;
|
||||
__le32 MaxDataCount;
|
||||
__le32 ParameterCount;
|
||||
__le32 ParameterOffset;
|
||||
__le32 DataCount;
|
||||
__le32 DataOffset;
|
||||
__u8 SetupCount; /* no setup words follow subcommand */
|
||||
/* SNIA spec incorrectly included spurious pad here */
|
||||
__le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */
|
||||
__le16 ByteCount; /* bcc = 3 + 8 */
|
||||
__u8 Pad[3];
|
||||
__u16 Fid;
|
||||
__u16 Reserved2;
|
||||
__le32 AclFlags;
|
||||
} __attribute__((packed)) QUERY_SEC_DESC_REQ;
|
||||
|
||||
typedef struct smb_com_transaction_change_notify_req {
|
||||
struct smb_hdr hdr; /* wct = 23 */
|
||||
__u8 MaxSetupCount;
|
||||
|
@ -1072,6 +1141,8 @@ typedef struct smb_com_transaction_change_notify_req {
|
|||
/* __u8 Data[1];*/
|
||||
} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
|
||||
|
||||
/* BB eventually change to use generic ntransact rsp struct
|
||||
and validation routine */
|
||||
typedef struct smb_com_transaction_change_notify_rsp {
|
||||
struct smb_hdr hdr; /* wct = 18 */
|
||||
__u8 Reserved[3];
|
||||
|
|
|
@ -48,8 +48,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
|
|||
struct smb_hdr * /* out */ ,
|
||||
int * /* bytes returned */ , const int long_op);
|
||||
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
|
||||
struct kvec *, int /* nvec */,
|
||||
int * /* bytes returned */ , const int long_op);
|
||||
struct kvec *, int /* nvec to send */,
|
||||
int * /* type of buf returned */ , const int long_op);
|
||||
extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
|
||||
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
|
||||
extern int is_valid_oplock_break(struct smb_hdr *smb);
|
||||
|
@ -94,7 +94,8 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||
|
||||
extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
|
||||
const char *searchName, const struct nls_table *nls_codepage,
|
||||
__u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
|
||||
__u16 *searchHandle, struct cifs_search_info * psrch_inf,
|
||||
int map, const char dirsep);
|
||||
|
||||
extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||
__u16 searchHandle, struct cifs_search_info * psrch_inf);
|
||||
|
@ -231,18 +232,17 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
|
|||
|
||||
extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, unsigned int count,
|
||||
const __u64 lseek, unsigned int *nbytes, char **buf);
|
||||
const __u64 lseek, unsigned int *nbytes, char **buf,
|
||||
int * return_buf_type);
|
||||
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, const unsigned int count,
|
||||
const __u64 lseek, unsigned int *nbytes,
|
||||
const char *buf, const char __user *ubuf,
|
||||
const int long_op);
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, const unsigned int count,
|
||||
const __u64 offset, unsigned int *nbytes,
|
||||
struct kvec *iov, const int nvec, const int long_op);
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName, __u64 * inode_number,
|
||||
const struct nls_table *nls_codepage,
|
||||
|
@ -269,6 +269,8 @@ extern void tconInfoFree(struct cifsTconInfo *);
|
|||
extern int cifs_reconnect(struct TCP_Server_Info *server);
|
||||
|
||||
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
|
||||
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
|
||||
__u32 *);
|
||||
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
|
||||
__u32 expected_sequence_number);
|
||||
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
|
||||
|
@ -297,6 +299,9 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
|
|||
const char *fileName, const char * ea_name,
|
||||
const void * ea_value, const __u16 ea_value_len,
|
||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
||||
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
|
||||
__u16 fid, char *acl_inf, const int buflen,
|
||||
const int acl_type /* ACCESS vs. DEFAULT */);
|
||||
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName,
|
||||
char *acl_inf, const int buflen,const int acl_type,
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "cifsproto.h"
|
||||
#include "cifs_unicode.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifsacl.h"
|
||||
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
static struct {
|
||||
|
@ -373,6 +374,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
if (rc == 0) {
|
||||
server->secMode = pSMBr->SecurityMode;
|
||||
if((server->secMode & SECMODE_USER) == 0)
|
||||
cFYI(1,("share mode security"));
|
||||
server->secType = NTLM; /* BB override default for
|
||||
NTLMv2 or kerberos v5 */
|
||||
/* one byte - no need to convert this or EncryptionKeyLen
|
||||
|
@ -383,7 +386,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||
min(le32_to_cpu(pSMBr->MaxBufferSize),
|
||||
(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
|
||||
server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
|
||||
cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
|
||||
cFYI(0, ("Max buf = %d", ses->server->maxBuf));
|
||||
GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
|
||||
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
|
||||
server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
|
||||
|
@ -411,8 +414,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||
(server->server_GUID,
|
||||
pSMBr->u.extended_response.
|
||||
GUID, 16) != 0) {
|
||||
cFYI(1,
|
||||
("UID of server does not match previous connection to same ip address"));
|
||||
cFYI(1, ("server UID changed"));
|
||||
memcpy(server->
|
||||
server_GUID,
|
||||
pSMBr->u.
|
||||
|
@ -958,21 +960,19 @@ openRetry:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* If no buffer passed in, then caller wants to do the copy
|
||||
as in the case of readpages so the SMB buffer must be
|
||||
freed by the caller */
|
||||
|
||||
int
|
||||
CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, const unsigned int count,
|
||||
const __u64 lseek, unsigned int *nbytes, char **buf)
|
||||
const __u64 lseek, unsigned int *nbytes, char **buf,
|
||||
int * pbuf_type)
|
||||
{
|
||||
int rc = -EACCES;
|
||||
READ_REQ *pSMB = NULL;
|
||||
READ_RSP *pSMBr = NULL;
|
||||
char *pReadData = NULL;
|
||||
int bytes_returned;
|
||||
int wct;
|
||||
int resp_buf_type = 0;
|
||||
struct kvec iov[1];
|
||||
|
||||
cFYI(1,("Reading %d bytes on fid %d",count,netfid));
|
||||
if(tcon->ses->capabilities & CAP_LARGE_FILES)
|
||||
|
@ -981,8 +981,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
|||
wct = 10; /* old style read */
|
||||
|
||||
*nbytes = 0;
|
||||
rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
|
||||
(void **) &pSMBr);
|
||||
rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -1010,9 +1009,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
|||
pSMBW->ByteCount = 0;
|
||||
}
|
||||
|
||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
iov[0].iov_base = (char *)pSMB;
|
||||
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
|
||||
rc = SendReceive2(xid, tcon->ses, iov,
|
||||
1 /* num iovecs */,
|
||||
&resp_buf_type, 0);
|
||||
cifs_stats_inc(&tcon->num_reads);
|
||||
pSMBr = (READ_RSP *)iov[0].iov_base;
|
||||
if (rc) {
|
||||
cERROR(1, ("Send error in read = %d", rc));
|
||||
} else {
|
||||
|
@ -1028,8 +1031,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
|||
rc = -EIO;
|
||||
*nbytes = 0;
|
||||
} else {
|
||||
pReadData =
|
||||
(char *) (&pSMBr->hdr.Protocol) +
|
||||
pReadData = (char *) (&pSMBr->hdr.Protocol) +
|
||||
le16_to_cpu(pSMBr->DataOffset);
|
||||
/* if(rc = copy_to_user(buf, pReadData, data_length)) {
|
||||
cERROR(1,("Faulting on read rc = %d",rc));
|
||||
|
@ -1039,16 +1041,27 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
|||
memcpy(*buf,pReadData,data_length);
|
||||
}
|
||||
}
|
||||
if(*buf)
|
||||
cifs_buf_release(pSMB);
|
||||
else
|
||||
*buf = (char *)pSMB;
|
||||
|
||||
cifs_small_buf_release(pSMB);
|
||||
if(*buf) {
|
||||
if(resp_buf_type == CIFS_SMALL_BUFFER)
|
||||
cifs_small_buf_release(iov[0].iov_base);
|
||||
else if(resp_buf_type == CIFS_LARGE_BUFFER)
|
||||
cifs_buf_release(iov[0].iov_base);
|
||||
} else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
|
||||
*buf = iov[0].iov_base;
|
||||
if(resp_buf_type == CIFS_SMALL_BUFFER)
|
||||
*pbuf_type = CIFS_SMALL_BUFFER;
|
||||
else if(resp_buf_type == CIFS_LARGE_BUFFER)
|
||||
*pbuf_type = CIFS_LARGE_BUFFER;
|
||||
}
|
||||
|
||||
/* Note: On -EAGAIN error only caller can retry on handle based calls
|
||||
since file handle passed in no longer valid */
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, const unsigned int count,
|
||||
|
@ -1155,7 +1168,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
|||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
int
|
||||
CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
||||
const int netfid, const unsigned int count,
|
||||
|
@ -1164,10 +1176,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
|||
{
|
||||
int rc = -EACCES;
|
||||
WRITE_REQ *pSMB = NULL;
|
||||
int bytes_returned, wct;
|
||||
int wct;
|
||||
int smb_hdr_len;
|
||||
int resp_buf_type = 0;
|
||||
|
||||
/* BB removeme BB */
|
||||
cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
|
||||
|
||||
if(tcon->ses->capabilities & CAP_LARGE_FILES)
|
||||
|
@ -1210,22 +1222,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
|||
pSMBW->ByteCount = cpu_to_le16(count + 5);
|
||||
}
|
||||
iov[0].iov_base = pSMB;
|
||||
if(wct == 14)
|
||||
iov[0].iov_len = smb_hdr_len + 4;
|
||||
else /* wct == 12 pad bigger by four bytes */
|
||||
iov[0].iov_len = smb_hdr_len + 8;
|
||||
|
||||
rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
|
||||
|
||||
rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
|
||||
long_op);
|
||||
cifs_stats_inc(&tcon->num_writes);
|
||||
if (rc) {
|
||||
cFYI(1, ("Send error Write2 = %d", rc));
|
||||
*nbytes = 0;
|
||||
} else if(resp_buf_type == 0) {
|
||||
/* presumably this can not happen, but best to be safe */
|
||||
rc = -EIO;
|
||||
*nbytes = 0;
|
||||
} else {
|
||||
WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
|
||||
WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
|
||||
*nbytes = le16_to_cpu(pSMBr->CountHigh);
|
||||
*nbytes = (*nbytes) << 16;
|
||||
*nbytes += le16_to_cpu(pSMBr->Count);
|
||||
}
|
||||
|
||||
cifs_small_buf_release(pSMB);
|
||||
if(resp_buf_type == CIFS_SMALL_BUFFER)
|
||||
cifs_small_buf_release(iov[0].iov_base);
|
||||
else if(resp_buf_type == CIFS_LARGE_BUFFER)
|
||||
cifs_buf_release(iov[0].iov_base);
|
||||
|
||||
/* Note: On -EAGAIN error only caller can retry on handle based calls
|
||||
since file handle passed in no longer valid */
|
||||
|
@ -1234,8 +1258,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
|||
}
|
||||
|
||||
|
||||
#endif /* CIFS_EXPERIMENTAL */
|
||||
|
||||
int
|
||||
CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
||||
const __u16 smb_file_id, const __u64 len,
|
||||
|
@ -1906,6 +1928,90 @@ querySymLinkRetry:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* Initialize NT TRANSACT SMB into small smb request buffer.
|
||||
This assumes that all NT TRANSACTS that we init here have
|
||||
total parm and data under about 400 bytes (to fit in small cifs
|
||||
buffer size), which is the case so far, it easily fits. NB:
|
||||
Setup words themselves and ByteCount
|
||||
MaxSetupCount (size of returned setup area) and
|
||||
MaxParameterCount (returned parms size) must be set by caller */
|
||||
static int
|
||||
smb_init_ntransact(const __u16 sub_command, const int setup_count,
|
||||
const int parm_len, struct cifsTconInfo *tcon,
|
||||
void ** ret_buf)
|
||||
{
|
||||
int rc;
|
||||
__u32 temp_offset;
|
||||
struct smb_com_ntransact_req * pSMB;
|
||||
|
||||
rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
|
||||
(void **)&pSMB);
|
||||
if (rc)
|
||||
return rc;
|
||||
*ret_buf = (void *)pSMB;
|
||||
pSMB->Reserved = 0;
|
||||
pSMB->TotalParameterCount = cpu_to_le32(parm_len);
|
||||
pSMB->TotalDataCount = 0;
|
||||
pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
|
||||
MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
|
||||
pSMB->ParameterCount = pSMB->TotalParameterCount;
|
||||
pSMB->DataCount = pSMB->TotalDataCount;
|
||||
temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
|
||||
(setup_count * 2) - 4 /* for rfc1001 length itself */;
|
||||
pSMB->ParameterOffset = cpu_to_le32(temp_offset);
|
||||
pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
|
||||
pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
|
||||
pSMB->SubCommand = cpu_to_le16(sub_command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
|
||||
int * pdatalen, int * pparmlen)
|
||||
{
|
||||
char * end_of_smb;
|
||||
__u32 data_count, data_offset, parm_count, parm_offset;
|
||||
struct smb_com_ntransact_rsp * pSMBr;
|
||||
|
||||
if(buf == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
pSMBr = (struct smb_com_ntransact_rsp *)buf;
|
||||
|
||||
/* ByteCount was converted from little endian in SendReceive */
|
||||
end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
|
||||
(char *)&pSMBr->ByteCount;
|
||||
|
||||
|
||||
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
||||
data_count = le32_to_cpu(pSMBr->DataCount);
|
||||
parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
|
||||
parm_count = le32_to_cpu(pSMBr->ParameterCount);
|
||||
|
||||
*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
|
||||
*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
|
||||
|
||||
/* should we also check that parm and data areas do not overlap? */
|
||||
if(*ppparm > end_of_smb) {
|
||||
cFYI(1,("parms start after end of smb"));
|
||||
return -EINVAL;
|
||||
} else if(parm_count + *ppparm > end_of_smb) {
|
||||
cFYI(1,("parm end after end of smb"));
|
||||
return -EINVAL;
|
||||
} else if(*ppdata > end_of_smb) {
|
||||
cFYI(1,("data starts after end of smb"));
|
||||
return -EINVAL;
|
||||
} else if(data_count + *ppdata > end_of_smb) {
|
||||
cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
|
||||
*ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
|
||||
return -EINVAL;
|
||||
} else if(parm_count + data_count > pSMBr->ByteCount) {
|
||||
cFYI(1,("parm count and data count larger than SMB"));
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName,
|
||||
|
@ -1928,7 +2034,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
|||
pSMB->TotalDataCount = 0;
|
||||
pSMB->MaxParameterCount = cpu_to_le32(2);
|
||||
/* BB find exact data count max from sess structure BB */
|
||||
pSMB->MaxDataCount = cpu_to_le32(4000);
|
||||
pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
|
||||
MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
|
||||
pSMB->MaxSetupCount = 4;
|
||||
pSMB->Reserved = 0;
|
||||
pSMB->ParameterOffset = 0;
|
||||
|
@ -1955,7 +2062,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
|||
rc = -EIO; /* bad smb */
|
||||
else {
|
||||
if(data_count && (data_count < 2048)) {
|
||||
char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
|
||||
char * end_of_smb = 2 /* sizeof byte count */ +
|
||||
pSMBr->ByteCount +
|
||||
(char *)&pSMBr->ByteCount;
|
||||
|
||||
struct reparse_data * reparse_buf = (struct reparse_data *)
|
||||
((char *)&pSMBr->hdr.Protocol + data_offset);
|
||||
|
@ -2199,6 +2308,7 @@ queryAclRetry:
|
|||
|
||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
cifs_stats_inc(&tcon->num_acl_get);
|
||||
if (rc) {
|
||||
cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
|
||||
} else {
|
||||
|
@ -2386,6 +2496,92 @@ GetExtAttrOut:
|
|||
|
||||
#endif /* CONFIG_POSIX */
|
||||
|
||||
|
||||
/* security id for everyone */
|
||||
const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
|
||||
/* group users */
|
||||
const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
|
||||
|
||||
/* Convert CIFS ACL to POSIX form */
|
||||
static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get Security Descriptor (by handle) from remote server for a file or dir */
|
||||
int
|
||||
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
||||
/* BB fix up return info */ char *acl_inf, const int buflen,
|
||||
const int acl_type /* ACCESS/DEFAULT not sure implication */)
|
||||
{
|
||||
int rc = 0;
|
||||
int buf_type = 0;
|
||||
QUERY_SEC_DESC_REQ * pSMB;
|
||||
struct kvec iov[1];
|
||||
|
||||
cFYI(1, ("GetCifsACL"));
|
||||
|
||||
rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
|
||||
8 /* parm len */, tcon, (void **) &pSMB);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pSMB->MaxParameterCount = cpu_to_le32(4);
|
||||
/* BB TEST with big acls that might need to be e.g. larger than 16K */
|
||||
pSMB->MaxSetupCount = 0;
|
||||
pSMB->Fid = fid; /* file handle always le */
|
||||
pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
|
||||
CIFS_ACL_DACL);
|
||||
pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
|
||||
pSMB->hdr.smb_buf_length += 11;
|
||||
iov[0].iov_base = (char *)pSMB;
|
||||
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
|
||||
|
||||
rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
|
||||
cifs_stats_inc(&tcon->num_acl_get);
|
||||
if (rc) {
|
||||
cFYI(1, ("Send error in QuerySecDesc = %d", rc));
|
||||
} else { /* decode response */
|
||||
struct cifs_sid * psec_desc;
|
||||
__le32 * parm;
|
||||
int parm_len;
|
||||
int data_len;
|
||||
int acl_len;
|
||||
struct smb_com_ntransact_rsp * pSMBr;
|
||||
|
||||
/* validate_nttransact */
|
||||
rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
|
||||
(char **)&psec_desc,
|
||||
&parm_len, &data_len);
|
||||
|
||||
if(rc)
|
||||
goto qsec_out;
|
||||
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
|
||||
|
||||
cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
|
||||
|
||||
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
|
||||
rc = -EIO; /* bad smb */
|
||||
goto qsec_out;
|
||||
}
|
||||
|
||||
/* BB check that data area is minimum length and as big as acl_len */
|
||||
|
||||
acl_len = le32_to_cpu(*(__le32 *)parm);
|
||||
/* BB check if(acl_len > bufsize) */
|
||||
|
||||
parse_sec_desc(psec_desc, acl_len);
|
||||
}
|
||||
qsec_out:
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
cifs_small_buf_release(iov[0].iov_base);
|
||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
||||
cifs_buf_release(iov[0].iov_base);
|
||||
cifs_small_buf_release(pSMB);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Legacy Query Path Information call for lookup to old servers such
|
||||
as Win9x/WinME */
|
||||
int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
|
||||
|
@ -4284,7 +4480,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
|
|||
{
|
||||
int rc = 0;
|
||||
struct smb_com_transaction_change_notify_req * pSMB = NULL;
|
||||
struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
|
||||
struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
|
||||
struct dir_notify_req *dnotify_req;
|
||||
int bytes_returned;
|
||||
|
||||
|
@ -4299,6 +4495,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
|
|||
pSMB->MaxParameterCount = cpu_to_le32(2);
|
||||
/* BB find exact data count max from sess structure BB */
|
||||
pSMB->MaxDataCount = 0; /* same in little endian or be */
|
||||
/* BB VERIFY verify which is correct for above BB */
|
||||
pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
|
||||
MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
|
||||
|
||||
pSMB->MaxSetupCount = 4;
|
||||
pSMB->Reserved = 0;
|
||||
pSMB->ParameterOffset = 0;
|
||||
|
|
|
@ -76,12 +76,19 @@ struct smb_vol {
|
|||
unsigned setuids:1;
|
||||
unsigned noperm:1;
|
||||
unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
|
||||
unsigned cifs_acl:1;
|
||||
unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
|
||||
unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
|
||||
unsigned direct_io:1;
|
||||
unsigned remap:1; /* set to remap seven reserved chars in filenames */
|
||||
unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
|
||||
unsigned sfu_emul:1;
|
||||
unsigned krb5:1;
|
||||
unsigned ntlm:1;
|
||||
unsigned ntlmv2:1;
|
||||
unsigned nullauth:1; /* attempt to authenticate with null user */
|
||||
unsigned sign:1;
|
||||
unsigned seal:1; /* encrypt */
|
||||
unsigned nocase; /* request case insensitive filenames */
|
||||
unsigned nobrl; /* disable sending byte range locks to srv */
|
||||
unsigned int rsize;
|
||||
|
@ -508,7 +515,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||
/* else length ok */
|
||||
reconnect = 0;
|
||||
|
||||
if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
|
||||
if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
|
||||
isLargeBuf = TRUE;
|
||||
memcpy(bigbuf, smallbuf, 4);
|
||||
smb_buffer = bigbuf;
|
||||
|
@ -777,7 +784,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
|||
|
||||
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
|
||||
vol->rw = TRUE;
|
||||
|
||||
vol->ntlm = TRUE;
|
||||
/* default is always to request posix paths. */
|
||||
vol->posix_paths = 1;
|
||||
|
||||
|
@ -903,6 +910,39 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
|||
printk(KERN_WARNING "CIFS: ip address too long\n");
|
||||
return 1;
|
||||
}
|
||||
} else if (strnicmp(data, "sec", 3) == 0) {
|
||||
if (!value || !*value) {
|
||||
cERROR(1,("no security value specified"));
|
||||
continue;
|
||||
} else if (strnicmp(value, "krb5i", 5) == 0) {
|
||||
vol->sign = 1;
|
||||
vol->krb5 = 1;
|
||||
} else if (strnicmp(value, "krb5p", 5) == 0) {
|
||||
/* vol->seal = 1;
|
||||
vol->krb5 = 1; */
|
||||
cERROR(1,("Krb5 cifs privacy not supported"));
|
||||
return 1;
|
||||
} else if (strnicmp(value, "krb5", 4) == 0) {
|
||||
vol->krb5 = 1;
|
||||
} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
|
||||
vol->ntlmv2 = 1;
|
||||
vol->sign = 1;
|
||||
} else if (strnicmp(value, "ntlmv2", 6) == 0) {
|
||||
vol->ntlmv2 = 1;
|
||||
} else if (strnicmp(value, "ntlmi", 5) == 0) {
|
||||
vol->ntlm = 1;
|
||||
vol->sign = 1;
|
||||
} else if (strnicmp(value, "ntlm", 4) == 0) {
|
||||
/* ntlm is default so can be turned off too */
|
||||
vol->ntlm = 1;
|
||||
} else if (strnicmp(value, "nontlm", 6) == 0) {
|
||||
vol->ntlm = 0;
|
||||
} else if (strnicmp(value, "none", 4) == 0) {
|
||||
vol->nullauth = 1;
|
||||
} else {
|
||||
cERROR(1,("bad security option: %s", value));
|
||||
return 1;
|
||||
}
|
||||
} else if ((strnicmp(data, "unc", 3) == 0)
|
||||
|| (strnicmp(data, "target", 6) == 0)
|
||||
|| (strnicmp(data, "path", 4) == 0)) {
|
||||
|
@ -1120,6 +1160,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
|||
vol->server_ino = 1;
|
||||
} else if (strnicmp(data, "noserverino",9) == 0) {
|
||||
vol->server_ino = 0;
|
||||
} else if (strnicmp(data, "cifsacl",7) == 0) {
|
||||
vol->cifs_acl = 1;
|
||||
} else if (strnicmp(data, "nocifsacl", 9) == 0) {
|
||||
vol->cifs_acl = 0;
|
||||
} else if (strnicmp(data, "acl",3) == 0) {
|
||||
vol->no_psx_acl = 0;
|
||||
} else if (strnicmp(data, "noacl",5) == 0) {
|
||||
|
@ -1546,7 +1590,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
cFYI(1, ("Username: %s ", volume_info.username));
|
||||
|
||||
} else {
|
||||
cifserror("No username specified ");
|
||||
cifserror("No username specified");
|
||||
/* In userspace mount helper we can get user name from alternate
|
||||
locations such as env variables and files on disk */
|
||||
kfree(volume_info.UNC);
|
||||
|
@ -1587,7 +1631,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
return -EINVAL;
|
||||
} else /* which servers DFS root would we conect to */ {
|
||||
cERROR(1,
|
||||
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
|
||||
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
|
||||
kfree(volume_info.UNC);
|
||||
kfree(volume_info.password);
|
||||
FreeXid(xid);
|
||||
|
@ -1626,7 +1670,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
|
||||
|
||||
if (srvTcp) {
|
||||
cFYI(1, ("Existing tcp session with server found "));
|
||||
cFYI(1, ("Existing tcp session with server found"));
|
||||
} else { /* create socket */
|
||||
if(volume_info.port)
|
||||
sin_server.sin_port = htons(volume_info.port);
|
||||
|
@ -1689,11 +1733,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
|
||||
if (existingCifsSes) {
|
||||
pSesInfo = existingCifsSes;
|
||||
cFYI(1, ("Existing smb sess found "));
|
||||
cFYI(1, ("Existing smb sess found"));
|
||||
kfree(volume_info.password);
|
||||
/* volume_info.UNC freed at end of function */
|
||||
} else if (!rc) {
|
||||
cFYI(1, ("Existing smb sess not found "));
|
||||
cFYI(1, ("Existing smb sess not found"));
|
||||
pSesInfo = sesInfoAlloc();
|
||||
if (pSesInfo == NULL)
|
||||
rc = -ENOMEM;
|
||||
|
@ -1751,7 +1795,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
cifs_sb->mnt_gid = volume_info.linux_gid;
|
||||
cifs_sb->mnt_file_mode = volume_info.file_mode;
|
||||
cifs_sb->mnt_dir_mode = volume_info.dir_mode;
|
||||
cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
|
||||
cFYI(1,("file mode: 0x%x dir mode: 0x%x",
|
||||
cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
|
||||
|
||||
if(volume_info.noperm)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
|
||||
|
@ -1767,6 +1812,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
|
||||
if(volume_info.nobrl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
|
||||
if(volume_info.cifs_acl)
|
||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
|
||||
|
||||
if(volume_info.direct_io) {
|
||||
cFYI(1,("mounting share using direct i/o"));
|
||||
|
@ -1777,7 +1824,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||
find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
|
||||
volume_info.username);
|
||||
if (tcon) {
|
||||
cFYI(1, ("Found match on UNC path "));
|
||||
cFYI(1, ("Found match on UNC path"));
|
||||
/* we can have only one retry value for a connection
|
||||
to a share so for resources mounted more than once
|
||||
to the same server share the last value passed in
|
||||
|
@ -1926,7 +1973,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
__u32 capabilities;
|
||||
__u16 count;
|
||||
|
||||
cFYI(1, ("In sesssetup "));
|
||||
cFYI(1, ("In sesssetup"));
|
||||
if(ses == NULL)
|
||||
return -EINVAL;
|
||||
user = ses->userName;
|
||||
|
@ -3202,9 +3249,26 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||
|
||||
pSMB->AndXCommand = 0xFF;
|
||||
pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
|
||||
pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
|
||||
bcc_ptr = &pSMB->Password[0];
|
||||
if((ses->server->secMode) & SECMODE_USER) {
|
||||
pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
|
||||
bcc_ptr++; /* skip password */
|
||||
} else {
|
||||
pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
|
||||
/* BB FIXME add code to fail this if NTLMv2 or Kerberos
|
||||
specified as required (when that support is added to
|
||||
the vfs in the future) as only NTLM or the much
|
||||
weaker LANMAN (which we do not send) is accepted
|
||||
by Samba (not sure whether other servers allow
|
||||
NTLMv2 password here) */
|
||||
SMBNTencrypt(ses->password,
|
||||
ses->server->cryptKey,
|
||||
bcc_ptr);
|
||||
|
||||
bcc_ptr += CIFS_SESSION_KEY_SIZE;
|
||||
*bcc_ptr = 0;
|
||||
bcc_ptr++; /* align */
|
||||
}
|
||||
|
||||
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||
|
@ -3222,7 +3286,6 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||
bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
|
||||
bcc_ptr += 2; /* skip trailing null */
|
||||
} else { /* ASCII */
|
||||
|
||||
strcpy(bcc_ptr, tree);
|
||||
bcc_ptr += strlen(tree) + 1;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* vfs operations that deal with dentries
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2003
|
||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -200,8 +200,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
(oplock & CIFS_CREATE_ACTION))
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
||||
(__u64)current->euid,
|
||||
(__u64)current->egid,
|
||||
(__u64)current->fsuid,
|
||||
(__u64)current->fsgid,
|
||||
0 /* dev */,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
|
@ -325,7 +325,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
|||
else if (pTcon->ses->capabilities & CAP_UNIX) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||
mode,(__u64)current->euid,(__u64)current->egid,
|
||||
mode,(__u64)current->fsuid,(__u64)current->fsgid,
|
||||
device_number, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
|
|
@ -553,13 +553,13 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
|||
}
|
||||
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
|
||||
if (ptmp) {
|
||||
/* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
|
||||
cFYI(1, ("closedir free smb buf in srch struct"));
|
||||
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
|
||||
cifs_buf_release(ptmp);
|
||||
}
|
||||
ptmp = pCFileStruct->search_resume_name;
|
||||
if (ptmp) {
|
||||
/* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
|
||||
cFYI(1, ("closedir free resume name"));
|
||||
pCFileStruct->search_resume_name = NULL;
|
||||
kfree(ptmp);
|
||||
}
|
||||
|
@ -868,10 +868,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
|||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
/* BB FIXME We can not sign across two buffers yet */
|
||||
if((experimEnabled) && ((pTcon->ses->server->secMode &
|
||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
|
||||
if((pTcon->ses->server->secMode &
|
||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
|
||||
struct kvec iov[2];
|
||||
unsigned int len;
|
||||
|
||||
|
@ -887,7 +886,6 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
|||
iov, 1, long_op);
|
||||
} else
|
||||
/* BB FIXME fixup indentation of line below */
|
||||
#endif
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
open_file->netfid,
|
||||
min_t(const int, cifs_sb->wsize,
|
||||
|
@ -1024,7 +1022,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
|||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
static int cifs_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
|
@ -1227,7 +1224,6 @@ retry:
|
|||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cifs_writepage(struct page* page, struct writeback_control *wbc)
|
||||
{
|
||||
|
@ -1426,6 +1422,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
|||
rc = -EAGAIN;
|
||||
smb_read_data = NULL;
|
||||
while (rc == -EAGAIN) {
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend)) {
|
||||
rc = cifs_reopen_file(file->f_dentry->d_inode,
|
||||
|
@ -1436,17 +1433,19 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
|
|||
rc = CIFSSMBRead(xid, pTcon,
|
||||
open_file->netfid,
|
||||
current_read_size, *poffset,
|
||||
&bytes_read, &smb_read_data);
|
||||
&bytes_read, &smb_read_data,
|
||||
&buf_type);
|
||||
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
|
||||
if (copy_to_user(current_offset,
|
||||
smb_read_data + 4 /* RFC1001 hdr */
|
||||
+ le16_to_cpu(pSMBr->DataOffset),
|
||||
bytes_read)) {
|
||||
rc = -EFAULT;
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
}
|
||||
if (smb_read_data) {
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
cifs_small_buf_release(smb_read_data);
|
||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
||||
cifs_buf_release(smb_read_data);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
|
@ -1480,6 +1479,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
|||
int xid;
|
||||
char *current_offset;
|
||||
struct cifsFileInfo *open_file;
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
|
||||
xid = GetXid();
|
||||
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
|
||||
|
@ -1518,7 +1518,8 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
|
|||
rc = CIFSSMBRead(xid, pTcon,
|
||||
open_file->netfid,
|
||||
current_read_size, *poffset,
|
||||
&bytes_read, ¤t_offset);
|
||||
&bytes_read, ¤t_offset,
|
||||
&buf_type);
|
||||
}
|
||||
if (rc || (bytes_read == 0)) {
|
||||
if (total_read) {
|
||||
|
@ -1616,6 +1617,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
struct smb_com_read_rsp *pSMBr;
|
||||
struct pagevec lru_pvec;
|
||||
struct cifsFileInfo *open_file;
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
|
||||
xid = GetXid();
|
||||
if (file->private_data == NULL) {
|
||||
|
@ -1674,11 +1676,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
rc = CIFSSMBRead(xid, pTcon,
|
||||
open_file->netfid,
|
||||
read_size, offset,
|
||||
&bytes_read, &smb_read_data);
|
||||
|
||||
&bytes_read, &smb_read_data,
|
||||
&buf_type);
|
||||
/* BB more RC checks ? */
|
||||
if (rc== -EAGAIN) {
|
||||
if (smb_read_data) {
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
cifs_small_buf_release(smb_read_data);
|
||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
||||
cifs_buf_release(smb_read_data);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
|
@ -1736,6 +1741,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
break;
|
||||
}
|
||||
if (smb_read_data) {
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
cifs_small_buf_release(smb_read_data);
|
||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
||||
cifs_buf_release(smb_read_data);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
|
@ -1746,6 +1754,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||
|
||||
/* need to free smb_read_data buf before exit */
|
||||
if (smb_read_data) {
|
||||
if(buf_type == CIFS_SMALL_BUFFER)
|
||||
cifs_small_buf_release(smb_read_data);
|
||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
||||
cifs_buf_release(smb_read_data);
|
||||
smb_read_data = NULL;
|
||||
}
|
||||
|
@ -1825,10 +1836,20 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
|
|||
open_file = find_writable_file(cifsInode);
|
||||
|
||||
if(open_file) {
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
|
||||
/* there is not actually a write pending so let
|
||||
this handle go free and allow it to
|
||||
be closable if needed */
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
|
||||
cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
|
||||
if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
|
||||
/* since no page cache to corrupt on directio
|
||||
we can change size safely */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
|
@ -1873,9 +1894,7 @@ struct address_space_operations cifs_addr_ops = {
|
|||
.readpage = cifs_readpage,
|
||||
.readpages = cifs_readpages,
|
||||
.writepage = cifs_writepage,
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.writepages = cifs_writepages,
|
||||
#endif
|
||||
.prepare_write = cifs_prepare_write,
|
||||
.commit_write = cifs_commit_write,
|
||||
.set_page_dirty = __set_page_dirty_nobuffers,
|
||||
|
|
|
@ -229,11 +229,12 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
|||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
int buf_type = CIFS_NO_BUFFER;
|
||||
/* Read header */
|
||||
rc = CIFSSMBRead(xid, pTcon,
|
||||
netfid,
|
||||
24 /* length */, 0 /* offset */,
|
||||
&bytes_read, &pbuf);
|
||||
&bytes_read, &pbuf, &buf_type);
|
||||
if((rc == 0) && (bytes_read >= 8)) {
|
||||
if(memcmp("IntxBLK", pbuf, 8) == 0) {
|
||||
cFYI(1,("Block device"));
|
||||
|
@ -750,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||
mode,
|
||||
(__u64)current->euid,
|
||||
(__u64)current->egid,
|
||||
(__u64)current->fsuid,
|
||||
(__u64)current->fsgid,
|
||||
0 /* dev_t */,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* fs/cifs/misc.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2004
|
||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
|
@ -161,6 +161,9 @@ cifs_buf_get(void)
|
|||
if (ret_buf) {
|
||||
memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
|
||||
atomic_inc(&bufAllocCount);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_inc(&totBufAllocCount);
|
||||
#endif /* CONFIG_CIFS_STATS2 */
|
||||
}
|
||||
|
||||
return ret_buf;
|
||||
|
@ -195,6 +198,10 @@ cifs_small_buf_get(void)
|
|||
/* No need to clear memory here, cleared in header assemble */
|
||||
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
|
||||
atomic_inc(&smBufAllocCount);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_inc(&totSmBufAllocCount);
|
||||
#endif /* CONFIG_CIFS_STATS2 */
|
||||
|
||||
}
|
||||
return ret_buf;
|
||||
}
|
||||
|
@ -292,7 +299,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
|||
struct cifsSesInfo * ses;
|
||||
char *temp = (char *) buffer;
|
||||
|
||||
memset(temp,0,MAX_CIFS_HDR_SIZE);
|
||||
memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */
|
||||
|
||||
buffer->smb_buf_length =
|
||||
(2 * word_count) + sizeof (struct smb_hdr) -
|
||||
|
@ -348,12 +355,12 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
|||
/* BB Add support for establishing new tCon and SMB Session */
|
||||
/* with userid/password pairs found on the smb session */
|
||||
/* for other target tcp/ip addresses BB */
|
||||
if(current->uid != treeCon->ses->linux_uid) {
|
||||
cFYI(1,("Multiuser mode and UID did not match tcon uid "));
|
||||
if(current->fsuid != treeCon->ses->linux_uid) {
|
||||
cFYI(1,("Multiuser mode and UID did not match tcon uid"));
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
list_for_each(temp_item, &GlobalSMBSessionList) {
|
||||
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
|
||||
if(ses->linux_uid == current->uid) {
|
||||
if(ses->linux_uid == current->fsuid) {
|
||||
if(ses->server == treeCon->ses->server) {
|
||||
cFYI(1,("found matching uid substitute right smb_uid"));
|
||||
buffer->Uid = ses->Suid;
|
||||
|
|
|
@ -214,8 +214,7 @@ static void fill_in_inode(struct inode *tmp_inode,
|
|||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop->lock = NULL;
|
||||
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
(cifs_sb->tcon->ses->server->maxBuf <
|
||||
|
@ -327,12 +326,18 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
if (S_ISREG(tmp_inode->i_mode)) {
|
||||
cFYI(1, ("File inode"));
|
||||
tmp_inode->i_op = &cifs_file_inode_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
|
||||
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop->lock = NULL;
|
||||
|
||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
|
||||
(cifs_sb->tcon->ses->server->maxBuf <
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
|
||||
|
||||
/* RFC 1002 session packet types */
|
||||
#define RFC1002_SESSION_MESASAGE 0x00
|
||||
#define RFC1002_SESSION_MESSAGE 0x00
|
||||
#define RFC1002_SESSION_REQUEST 0x81
|
||||
#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
|
||||
#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
|
||||
#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
|
||||
#define RFC1002_RETARGET_SESSION_RESPONSE 0x84
|
||||
#define RFC1002_SESSION_KEEP_ALIVE 0x85
|
||||
|
||||
/* RFC 1002 flags (only one defined */
|
||||
|
|
|
@ -206,7 +206,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
|||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
static int
|
||||
smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
||||
struct sockaddr *sin)
|
||||
|
@ -299,7 +298,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
|||
|
||||
int
|
||||
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
struct kvec *iov, int n_vec, int *pbytes_returned,
|
||||
struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
|
||||
const int long_op)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -308,6 +307,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
struct mid_q_entry *midQ;
|
||||
struct smb_hdr *in_buf = iov[0].iov_base;
|
||||
|
||||
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
|
||||
|
||||
if (ses == NULL) {
|
||||
cERROR(1,("Null smb session"));
|
||||
return -EIO;
|
||||
|
@ -392,8 +393,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* BB FIXME */
|
||||
/* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
|
||||
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
|
||||
|
||||
midQ->midState = MID_REQUEST_SUBMITTED;
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
|
@ -489,21 +489,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
receive_len, xid));
|
||||
rc = -EIO;
|
||||
} else { /* rcvd frame is ok */
|
||||
|
||||
if (midQ->resp_buf &&
|
||||
(midQ->midState == MID_RESPONSE_RECEIVED)) {
|
||||
in_buf->smb_buf_length = receive_len;
|
||||
/* BB verify that length would not overrun small buf */
|
||||
memcpy((char *)in_buf + 4,
|
||||
(char *)midQ->resp_buf + 4,
|
||||
receive_len);
|
||||
|
||||
dump_smb(in_buf, 80);
|
||||
iov[0].iov_base = (char *)midQ->resp_buf;
|
||||
if(midQ->largeBuf)
|
||||
*pRespBufType = CIFS_LARGE_BUFFER;
|
||||
else
|
||||
*pRespBufType = CIFS_SMALL_BUFFER;
|
||||
iov[0].iov_len = receive_len + 4;
|
||||
iov[1].iov_len = 0;
|
||||
|
||||
dump_smb(midQ->resp_buf, 80);
|
||||
/* convert the length into a more usable form */
|
||||
if((receive_len > 24) &&
|
||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||
SECMODE_SIGN_ENABLED))) {
|
||||
rc = cifs_verify_signature(in_buf,
|
||||
rc = cifs_verify_signature(midQ->resp_buf,
|
||||
ses->server->mac_signing_key,
|
||||
midQ->sequence_number+1);
|
||||
if(rc) {
|
||||
|
@ -512,18 +514,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
}
|
||||
}
|
||||
|
||||
*pbytes_returned = in_buf->smb_buf_length;
|
||||
|
||||
/* BB special case reconnect tid and uid here? */
|
||||
/* BB special case Errbadpassword and pwdexpired here */
|
||||
rc = map_smb_to_linux_error(in_buf);
|
||||
rc = map_smb_to_linux_error(midQ->resp_buf);
|
||||
|
||||
/* convert ByteCount if necessary */
|
||||
if (receive_len >=
|
||||
sizeof (struct smb_hdr) -
|
||||
4 /* do not count RFC1001 header */ +
|
||||
(2 * in_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf));
|
||||
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(midQ->resp_buf) =
|
||||
le16_to_cpu(BCC_LE(midQ->resp_buf));
|
||||
midQ->resp_buf = NULL; /* mark it so will not be freed
|
||||
by DeleteMidQEntry */
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cFYI(1,("Bad MID state?"));
|
||||
|
@ -549,7 +552,6 @@ out_unlock2:
|
|||
|
||||
return rc;
|
||||
}
|
||||
#endif /* CIFS_EXPERIMENTAL */
|
||||
|
||||
int
|
||||
SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
|
@ -790,7 +792,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cERROR(1,("Bad MID state? "));
|
||||
cERROR(1,("Bad MID state?"));
|
||||
}
|
||||
}
|
||||
cifs_no_response_exit:
|
||||
|
|
|
@ -254,7 +254,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
|||
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
|
||||
buf_size, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
|
||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
|
||||
strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if(sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
||||
|
@ -262,10 +263,27 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
|||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
__u16 fid;
|
||||
int oplock = FALSE;
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
||||
FILE_OPEN, GENERIC_READ, 0, &fid,
|
||||
&oplock, NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if(rc == 0) {
|
||||
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
|
||||
ea_value, buf_size,
|
||||
ACL_TYPE_ACCESS);
|
||||
CIFSSMBClose(xid, pTcon, fid)
|
||||
}
|
||||
} */ /* BB enable after fixing up return data */
|
||||
|
||||
#else
|
||||
cFYI(1,("query POSIX ACL not supported yet"));
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,
|
||||
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if(sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
||||
|
|
Loading…
Reference in a new issue