Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] Fix check after use error in ACL code
  [CIFS] Fix potential data corruption when writing out cached dirty pages
  [CIFS] Fix spurious reconnect on 2nd peek from read of SMB length
  [CIFS] remove build warning
  [CIFS] Have CIFS_SessSetup build correct SPNEGO SessionSetup request
  [CIFS] minor checkpatch cleanup
  [CIFS] have cifs_get_spnego_key get the hostname from TCP_Server_Info
  [CIFS] add hostname field to TCP_Server_Info struct
  [CIFS] clean up error handling in cifs_mount
  [CIFS] add ver= prefix to upcall format version
  [CIFS] Fix buffer overflow if server sends corrupt response to small
  • Loading branch information
Linus Torvalds committed Nov 27, 2007
2 parents 3050d45 + 2b83457 commit bb40784
Show file tree
Hide file tree
Showing 15 changed files with 367 additions and 228 deletions.
3 changes: 3 additions & 0 deletions fs/cifs/CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Version 1.52
------------
Fix oops on second mount to server when null auth is used.
Enable experimental Kerberos support. Return writebehind errors on flush
and sync so that events like out of disk space get reported properly on
cached files.

Version 1.51
------------
Expand Down
27 changes: 12 additions & 15 deletions fs/cifs/README
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,9 @@ If no password is provided, mount.cifs will prompt for password entry

Restrictions
============
Servers must support the NTLM SMB dialect (which is the most recent, supported
by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
problem as most servers support this. IPv6 support is planned for the future,
and is almost complete.
1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a
problem as most servers support this.

Valid filenames differ between Windows and Linux. Windows typically restricts
filenames which contain certain reserved characters (e.g.the character :
Expand Down Expand Up @@ -458,6 +455,8 @@ A partial list of the supported mount options follows:
byte range locks).
remount remount the share (often used to change from ro to rw mounts
or vice versa)
cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for
the file. (EXPERIMENTAL)
servern Specify the server 's netbios name (RFC1001 name) to use
when attempting to setup a session to the server. This is
This is needed for mounting to some older servers (such
Expand Down Expand Up @@ -584,8 +583,8 @@ Experimental When set to 1 used to enable certain experimental
performance enhancement was disabled when
signing turned on in case buffer was modified
just before it was sent, also this flag will
be used to use the new experimental sessionsetup
code).
be used to use the new experimental directory change
notification code).

These experimental features and tracing can be enabled by changing flags in
/proc/fs/cifs (after the cifs module has been installed or built into the
Expand All @@ -608,7 +607,8 @@ the start of smb requests and responses can be enabled via:
Two other experimental features are under development. To test these
requires enabling CONFIG_CIFS_EXPERIMENTAL

ipv6 enablement
cifsacl support needed to retrieve approximated mode bits based on
the contents on the CIFS ACL.

DNOTIFY fcntl: needed for support of directory change
notification and perhaps later for file leases)
Expand All @@ -625,10 +625,7 @@ that they represent all for that share, not just those for which the server
returned success.

Also note that "cat /proc/fs/cifs/DebugData" will display information about
the active sessions and the shares that are mounted. Note: NTLMv2 enablement
will not work since its implementation is not quite complete yet. Do not alter
the ExtendedSecurity configuration value unless you are doing specific testing.
Enabling extended security works to Windows 2000 Workstations and XP but not to
Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
complete in the CIFS VFS yet).
the active sessions and the shares that are mounted.
Enabling Kerberos (extended security) works when CONFIG_CIFS_EXPERIMENTAL is enabled
but requires a user space helper (from the Samba project). NTLM and NTLMv2 and
LANMAN support do not require this helpr.
2 changes: 1 addition & 1 deletion fs/cifs/TODO
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SecurityDescriptors
c) Better pam/winbind integration (e.g. to handle uid mapping
better)

d) Kerberos/SPNEGO session setup support - (started)
d) Verify that Kerberos signing works

e) Cleanup now unneeded SessSetup code in
fs/cifs/connect.c and add back in NTLMSSP code if any servers
Expand Down
20 changes: 13 additions & 7 deletions fs/cifs/cifs_spnego.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,26 @@ struct key_type cifs_spnego_key_type = {
.describe = user_describe,
};

#define MAX_VER_STR_LEN 9 /* length of longest version string e.g.
strlen(";ver=0xFF") */
#define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg
in future could have strlen(";sec=ntlmsspi") */
#define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */
/* get a key struct with a SPNEGO security blob, suitable for session setup */
struct key *
cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname)
cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
{
struct TCP_Server_Info *server = sesInfo->server;
char *description, *dp;
size_t desc_len;
struct key *spnego_key;
const char *hostname = server->hostname;


/* version + ;ip{4|6}= + address + ;host=hostname +
;sec= + ;uid= + NULL */
desc_len = 4 + 5 + 32 + 1 + 5 + strlen(hostname) +
strlen(";sec=krb5") + 7 + sizeof(uid_t)*2 + 1;
/* BB: come up with better scheme for determining length */
/* length of fields (with semicolons): ver=0xyz ipv4= ipaddress host=
hostname sec=mechanism uid=0x uid */
desc_len = MAX_VER_STR_LEN + 5 + MAX_IPV6_ADDR_LEN + 1 + 6 +
strlen(hostname) + MAX_MECH_STR_LEN + 8 + (sizeof(uid_t) * 2);
spnego_key = ERR_PTR(-ENOMEM);
description = kzalloc(desc_len, GFP_KERNEL);
if (description == NULL)
Expand All @@ -88,7 +94,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname)
dp = description;
/* start with version and hostname portion of UNC string */
spnego_key = ERR_PTR(-EINVAL);
sprintf(dp, "0x%2.2x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
hostname);
dp = description + strlen(description);

Expand Down
1 change: 1 addition & 0 deletions fs/cifs/cifs_spnego.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct cifs_spnego_msg {

#ifdef __KERNEL__
extern struct key_type cifs_spnego_key_type;
extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo);
#endif /* KERNEL */

#endif /* _CIFS_SPNEGO_H */
13 changes: 7 additions & 6 deletions fs/cifs/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,13 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,

/* BB need to add parm so we can store the SID BB */

if (!pdacl) {
/* no DACL in the security descriptor, set
all the permissions for user/group/other */
inode->i_mode |= S_IRWXUGO;
return;
}

/* validate that we do not go past end of acl */
if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
cERROR(1, ("ACL too small to parse DACL"));
Expand All @@ -286,12 +293,6 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
user/group/other have no permissions */
inode->i_mode &= ~(S_IRWXUGO);

if (!pdacl) {
/* no DACL in the security descriptor, set
all the permissions for user/group/other */
inode->i_mode |= S_IRWXUGO;
return;
}
acl_base = (char *)pdacl;
acl_size = sizeof(struct cifs_acl);

Expand Down
7 changes: 5 additions & 2 deletions fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->cifsAttrs = 0x20; /* default */
atomic_set(&cifs_inode->inUse, 0);
cifs_inode->time = 0;
cifs_inode->write_behind_rc = 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 */
Expand Down Expand Up @@ -852,7 +853,7 @@ static int cifs_oplock_thread(void *dummyarg)
struct cifsTconInfo *pTcon;
struct inode *inode;
__u16 netfid;
int rc;
int rc, waitrc = 0;

set_freezable();
do {
Expand Down Expand Up @@ -884,9 +885,11 @@ static int cifs_oplock_thread(void *dummyarg)
filemap_fdatawrite(inode->i_mapping);
if (CIFS_I(inode)->clientCanCacheRead
== 0) {
filemap_fdatawait(inode->i_mapping);
waitrc = filemap_fdatawait(inode->i_mapping);
invalidate_remote_inode(inode);
}
if (rc == 0)
rc = waitrc;
} else
rc = 0;
/* mutex_unlock(&inode->i_mutex);*/
Expand Down
13 changes: 13 additions & 0 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ struct mac_key {
unsigned int len;
union {
char ntlm[CIFS_SESS_KEY_SIZE + 16];
char krb5[CIFS_SESS_KEY_SIZE + 16]; /* BB: length correct? */
struct {
char key[16];
struct ntlmv2_resp resp;
Expand Down Expand Up @@ -139,6 +140,7 @@ struct TCP_Server_Info {
/* 15 character server name + 0x20 16th byte indicating type = srv */
char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];
char *hostname; /* hostname portion of UNC string */
struct socket *ssocket;
union {
struct sockaddr_in sockAddr;
Expand Down Expand Up @@ -471,6 +473,17 @@ struct dir_notify_req {
#define CIFS_LARGE_BUFFER 2
#define CIFS_IOVEC 4 /* array of response buffers */

/* Type of Request to SendReceive2 */
#define CIFS_STD_OP 0 /* normal request timeout */
#define CIFS_LONG_OP 1 /* long op (up to 45 sec, oplock time) */
#define CIFS_VLONG_OP 2 /* sloow op - can take up to 180 seconds */
#define CIFS_BLOCKING_OP 4 /* operation can block */
#define CIFS_ASYNC_OP 8 /* do not wait for response */
#define CIFS_TIMEOUT_MASK 0x00F /* only one of 5 above set in req */
#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */
#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */
#define CIFS_NO_RESP 0x040 /* no response buffer required */

/* Security Flags: indicate type of session setup needed */
#define CIFSSEC_MAY_SIGN 0x00001
#define CIFSSEC_MAY_NTLM 0x00002
Expand Down
17 changes: 8 additions & 9 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
struct smb_hdr * /* input */ ,
struct smb_hdr * /* out */ ,
int * /* bytes returned */ , const int long_op);
extern int SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
struct smb_hdr *in_buf, int flags);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */ , const int long_op,
const int logError /* whether to log status code*/ );
int * /* type of buf returned */ , const int flags);
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
struct cifsTconInfo *,
struct smb_hdr * /* input */ ,
Expand All @@ -76,8 +77,6 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifsSesInfo *ses,
void **request_buf);
extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo,
const char *hostname);
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
const int stage,
const struct nls_table *nls_cp);
Expand Down Expand Up @@ -248,15 +247,15 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid,
extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int disposition,
const int access_flags, const int omode,
__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
__u16 *netfid, int *pOplock, FILE_ALL_INFO *,
const struct nls_table *nls_codepage, int remap);
extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int disposition,
const int access_flags, const int omode,
__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
__u16 *netfid, int *pOplock, FILE_ALL_INFO *,
const struct nls_table *nls_codepage, int remap);
extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
u32 posix_flags, __u64 mode, __u16 * netfid,
u32 posix_flags, __u64 mode, __u16 *netfid,
FILE_UNIX_BASIC_INFO *pRetData,
__u32 *pOplock, const char *name,
const struct nls_table *nls_codepage, int remap);
Expand All @@ -277,7 +276,7 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
const __u64 offset, unsigned int *nbytes,
struct kvec *iov, const int nvec, const int long_op);
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, __u64 * inode_number,
const unsigned char *searchName, __u64 *inode_number,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
Expand Down Expand Up @@ -352,5 +351,5 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
const char *local_acl, const int buflen, const int acl_type,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
#endif /* _CIFSPROTO_H */
Loading

0 comments on commit bb40784

Please sign in to comment.