Commit 2843483d authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (51 commits)
  [CIFS] log better errors on failed mounts
  [CIFS] Return better error when server requires signing but client forbids
  [CIFS] fix typo
  [CIFS] acl support part 4
  [CIFS] Fix minor problems noticed by scan
  [CIFS] fix bad handling of EAGAIN error on kernel_recvmsg in cifs_demultiplex_thread
  [CIFS] build break
  [CIFS] endian fixes
  [CIFS] endian fixes in new acl code
  [CIFS] Fix some endianness problems in new acl code
  [CIFS] missing #endif from a previous patch
  [CIFS] formatting fixes
  [CIFS] Break up unicode_sessetup string functions
  [CIFS] parse server_GUID in SPNEGO negProt response
  [CIFS]
  [CIFS] Fix endian conversion problem in posix mkdir
  [CIFS] fix build break when lanman not enabled
  [CIFS] remove two sparse warnings
  [CIFS] remove compile warnings when debug disabled
  [CIFS] CIFS ACL support part 3
  ...
parents 26790656 a761ac57
Version 1.51
------------
Fix memory leak in statfs when mounted to very old servers (e.g.
Windows 9x). Add new feature "POSIX open" which allows servers
which support the current POSIX Extensions to provide better semantics
(e.g. delete for open files opened with posix open). Take into
account umask on posix mkdir not just older style mkdir. Add
ability to mount to IPC$ share (which allows CIFS named pipes to be
opened, read and written as if they were files). When 1st tree
connect fails (e.g. due to signing negotiation failure) fix
leak that causes cifsd not to stop and rmmod to fail to cleanup
cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
bigendian architectures. Fix possible memory corruption when
EAGAIN returned on kern_recvmsg. Return better error if server
requires packet signing but client has disabled it.
Version 1.50
------------
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
......@@ -6,7 +22,10 @@ done with "serverino" mount option). Add support for POSIX Unlink
Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix"
mount option to allow disabling the CIFS Unix Extensions for just
that mount. Fix hang on spinlock in find_writable_file (race when
reopening file after session crash).
reopening file after session crash). Byte range unlock request to
windows server could unlock more bytes (on server copy of file)
than intended if start of unlock request is well before start of
a previous byte range lock that we issued.
Version 1.49
------------
......
......@@ -3,4 +3,4 @@
#
obj-$(CONFIG_CIFS) += cifs.o
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifsacl.o
......@@ -385,10 +385,9 @@ asn1_oid_decode(struct asn1_ctx *ctx,
unsigned long *optr;
size = eoc - ctx->pointer + 1;
*oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
if (*oid == NULL) {
*oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
if (*oid == NULL)
return 0;
}
optr = *oid;
......@@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
......
......@@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
length =
sprintf(buf,
"\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
"Attributes: 0x%x\nPathComponentMax: %d Status: %d",
i, tcon->treeName,
atomic_read(&tcon->useCount),
tcon->nativeFileSystem,
length = sprintf(buf, "\n%d) %s Uses: %d ", i,
tcon->treeName, atomic_read(&tcon->useCount));
buf += length;
if (tcon->nativeFileSystem) {
length = sprintf(buf, "Type: %s ",
tcon->nativeFileSystem);
buf += length;
}
length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x"
"\nPathComponentMax: %d Status: %d",
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
......@@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer,
if (count < 3) {
/* single char or single char followed by null */
c = flags_string[0];
if (c == '0' || c == 'n' || c == 'N')
if (c == '0' || c == 'n' || c == 'N') {
extended_security = CIFSSEC_DEF; /* default */
else if (c == '1' || c == 'y' || c == 'Y')
return count;
} else if (c == '1' || c == 'y' || c == 'Y') {
extended_security = CIFSSEC_MAX;
return count;
return count;
} else if (!isdigit(c)) {
cERROR(1, ("invalid flag %c", c));
return -EINVAL;
}
}
/* else we have a number */
......
/*
* fs/cifs/cifsacl.c
*
* Copyright (C) International Business Machines Corp., 2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for mapping CIFS/NTFS ACLs
*
* 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
*/
#include <linux/fs.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsacl.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL
static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
{{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
{{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
{{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
{{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"}
};
/* security id for everyone */
static const struct cifs_sid sid_everyone =
{1, 1, {0, 0, 0, 0, 0, 0}, {} };
/* group users */
static const struct cifs_sid sid_user =
{1, 2 , {0, 0, 0, 0, 0, 5}, {} };
int match_sid(struct cifs_sid *ctsid)
{
int i, j;
int num_subauth, num_sat, num_saw;
struct cifs_sid *cwsid;
if (!ctsid)
return (-1);
for (i = 0; i < NUM_WK_SIDS; ++i) {
cwsid = &(wksidarr[i].cifssid);
/* compare the revision */
if (ctsid->revision != cwsid->revision)
continue;
/* compare all of the six auth values */
for (j = 0; j < 6; ++j) {
if (ctsid->authority[j] != cwsid->authority[j])
break;
}
if (j < 6)
continue; /* all of the auth values did not match */
/* compare all of the subauth values if any */
num_sat = ctsid->num_subauth;
num_saw = cwsid->num_subauth;
num_subauth = num_sat < num_saw ? num_sat : num_saw;
if (num_subauth) {
for (j = 0; j < num_subauth; ++j) {
if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
break;
}
if (j < num_subauth)
continue; /* all sub_auth values do not match */
}
cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
return (0); /* sids compare/match */
}
cFYI(1, ("No matching sid"));
return (-1);
}
/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
the same returns 1, if they do not match returns 0 */
int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
{
int i;
int num_subauth, num_sat, num_saw;
if ((!ctsid) || (!cwsid))
return (0);
/* compare the revision */
if (ctsid->revision != cwsid->revision)
return (0);
/* compare all of the six auth values */
for (i = 0; i < 6; ++i) {
if (ctsid->authority[i] != cwsid->authority[i])
return (0);
}
/* compare all of the subauth values if any */
num_sat = ctsid->num_subauth;
num_saw = cwsid->num_subauth;
num_subauth = num_sat < num_saw ? num_sat : num_saw;
if (num_subauth) {
for (i = 0; i < num_subauth; ++i) {
if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
return (0);
}
}
return (1); /* sids compare/match */
}
static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
{
int num_subauth;
/* validate that we do not go past end of acl */
/* XXX this if statement can be removed
if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
cERROR(1, ("ACL too small to parse ACE"));
return;
} */
num_subauth = pace->num_subauth;
if (num_subauth) {
#ifdef CONFIG_CIFS_DEBUG2
int i;
cFYI(1, ("ACE revision %d num_subauth %d",
pace->revision, pace->num_subauth));
for (i = 0; i < num_subauth; ++i) {
cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
le32_to_cpu(pace->sub_auth[i])));
}
/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */
cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1])));
#endif
}
return;
}
static void parse_ntace(struct cifs_ntace *pntace, char *end_of_acl)
{
/* validate that we do not go past end of acl */
if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) {
cERROR(1, ("ACL too small to parse NT ACE"));
return;
}
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x",
pntace->type, pntace->flags, pntace->size,
pntace->access_req));
#endif
return;
}
static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid)
{
int i;
int num_aces = 0;
int acl_size;
char *acl_base;
struct cifs_ntace **ppntace;
struct cifs_ace **ppace;
/* BB need to add parm so we can store the SID BB */
/* 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"));
return;
}
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("DACL revision %d size %d num aces %d",
le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
le32_to_cpu(pdacl->num_aces)));
#endif
acl_base = (char *)pdacl;
acl_size = sizeof(struct cifs_acl);
num_aces = le32_to_cpu(pdacl->num_aces);
if (num_aces > 0) {
ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *),
GFP_KERNEL);
ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
GFP_KERNEL);
/* cifscred->cecount = pdacl->num_aces;
cifscred->ntaces = kmalloc(num_aces *
sizeof(struct cifs_ntace *), GFP_KERNEL);
cifscred->aces = kmalloc(num_aces *
sizeof(struct cifs_ace *), GFP_KERNEL);*/
for (i = 0; i < num_aces; ++i) {
ppntace[i] = (struct cifs_ntace *)
(acl_base + acl_size);
ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] +
sizeof(struct cifs_ntace));
parse_ntace(ppntace[i], end_of_acl);
if (end_of_acl < ((char *)ppace[i] +
(le16_to_cpu(ppntace[i]->size) -
sizeof(struct cifs_ntace)))) {
cERROR(1, ("ACL too small to parse ACE"));
break;
} else
parse_ace(ppace[i], end_of_acl);
/* memcpy((void *)(&(cifscred->ntaces[i])),
(void *)ppntace[i],
sizeof(struct cifs_ntace));
memcpy((void *)(&(cifscred->aces[i])),
(void *)ppace[i],
sizeof(struct cifs_ace)); */
acl_base = (char *)ppntace[i];
acl_size = le16_to_cpu(ppntace[i]->size);
}
kfree(ppace);
kfree(ppntace);
}
return;
}
static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
{
/* BB need to add parm so we can store the SID BB */
/* validate that we do not go past end of acl */
if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) {
cERROR(1, ("ACL too small to parse SID"));
return -EINVAL;
}
if (psid->num_subauth) {
#ifdef CONFIG_CIFS_DEBUG2
int i;
cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
psid->revision, psid->num_subauth, psid->sub_auth[0]));
for (i = 0; i < psid->num_subauth; i++) {
cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
le32_to_cpu(psid->sub_auth[i])));
}
/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */
cFYI(1, ("RID 0x%x",
le32_to_cpu(psid->sub_auth[psid->num_subauth-1])));
#endif
}
return 0;
}
/* Convert CIFS ACL to POSIX form */
int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
{
int rc;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
char *end_of_acl = ((char *)pntsd) + acl_len;
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
dacl_ptr = (struct cifs_acl *)((char *)pntsd +
le32_to_cpu(pntsd->dacloffset));
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
"sacloffset 0x%x dacloffset 0x%x",
pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
le32_to_cpu(pntsd->gsidoffset),
le32_to_cpu(pntsd->sacloffset),
le32_to_cpu(pntsd->dacloffset)));
#endif
rc = parse_sid(owner_sid_ptr, end_of_acl);
if (rc)
return rc;
rc = parse_sid(group_sid_ptr, end_of_acl);
if (rc)
return rc;
parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr);
/* cifscred->uid = owner_sid_ptr->rid;
cifscred->gid = group_sid_ptr->rid;
memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
sizeof (struct cifs_sid));
memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
sizeof (struct cifs_sid)); */
return (0);
}
#endif /* CONFIG_CIFS_EXPERIMENTAL */
/*
* fs/cifs/cifsacl.h
*
* Copyright (c) International Business Machines Corp., 2005
* Copyright (c) International Business Machines Corp., 2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
......@@ -22,17 +22,65 @@
#ifndef _CIFSACL_H
#define _CIFSACL_H
#define NUM_AUTHS 6 /* number of authority fields */
#define NUM_SUBAUTHS 5 /* number of sub authority fields */
#define NUM_WK_SIDS 7 /* number of well known sids */
#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
#define READ_BIT 0x4
#define WRITE_BIT 0x2
#define EXEC_BIT 0x1
#define UBITSHIFT 6
#define GBITSHIFT 3
struct cifs_ntsd {
__le16 revision; /* revision level */
__le16 type;
__le32 osidoffset;
__le32 gsidoffset;
__le32 sacloffset;
__le32 dacloffset;
} __attribute__((packed));
struct cifs_sid {
__u8 revision; /* revision level */
__u8 num_subauths;
__u8 num_subauth;
__u8 authority[6];
__le32 sub_auth[5]; /* sub_auth[num_subauth] */ /* BB FIXME endianness BB */
} __attribute__((packed));
struct cifs_acl {
__le16 revision; /* revision level */
__le16 size;
__le32 num_aces;
} __attribute__((packed));
struct cifs_ntace { /* first part of ACE which contains perms */
__u8 type;
__u8 flags;
__le16 size;
__le32 access_req;
} __attribute__((packed));
struct cifs_ace { /* last part of ACE which includes user info */
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[6];
__u32 sub_auth[4];
/* next sub_auth if any ... */
__le32 sub_auth[5];
} __attribute__((packed));
/* everyone */
/* extern const struct cifs_sid sid_everyone;*/
/* group users */
/* extern const struct cifs_sid sid_user;*/
struct cifs_wksid {
struct cifs_sid cifssid;
char sidname[SIDNAMELENGTH];
} __attribute__((packed));
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern int match_sid(struct cifs_sid *);
extern int compare_sids(struct cifs_sid *, struct cifs_sid *);
#endif /* CONFIG_CIFS_EXPERIMENTAL */
#endif /* _CIFSACL_H */
......@@ -345,7 +345,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL)
goto calc_exit_2;
len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
UniStrupr(user);
hmac_md5_update((char *)user, 2*len, pctxt);
......@@ -356,7 +356,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if (domain == NULL)
goto calc_exit_1;
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
nls_cp);
/* the following line was removed since it didn't work well
with lower cased domain name that passed as an option.
Maybe converting the domain name earlier makes sense */
......
......@@ -49,10 +49,6 @@
static struct quotactl_ops cifs_quotactl_ops;
#endif /* QUOTA */
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
int cifsFYI = 0;
int cifsERROR = 1;
int traceSMB = 0;
......@@ -240,9 +236,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
cifs_sb = CIFS_SB(inode->i_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
return 0;
} else /* file mode might have been restricted at mount time
else /* file mode might have been restricted at mount time
on the client (above and beyond ACL on servers) for
servers which do not support setting and viewing mode bits,
so allowing client to check permissions is useful */
......@@ -312,15 +308,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
seq_printf(s, ",domain=%s",
cifs_sb->tcon->ses->domainName);
}
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_printf(s, ",posixpaths");
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
}
......@@ -346,7 +342,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
if (pTcon) {
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
} else {
return -EIO;
rc = -EIO;
}
FreeXid(xid);
......@@ -716,7 +712,7 @@ static int
cifs_init_inodecache(void)
{
cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
sizeof (struct cifsInodeInfo),
sizeof(struct cifsInodeInfo),
0, (SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD),
cifs_init_once);
......@@ -816,8 +812,8 @@ static int
cifs_init_mids(void)
{
cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
sizeof (struct mid_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL);
sizeof(struct mid_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL);
if (cifs_mid_cachep == NULL)
return -ENOMEM;
......@@ -829,8 +825,8 @@ cifs_init_mids(void)
}
cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
sizeof (struct oplock_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL);
sizeof(struct oplock_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL);
if (cifs_oplock_cachep == NULL) {
mempool_destroy(cifs_mid_poolp);
kmem_cache_destroy(cifs_mid_cachep);
......@@ -882,7 +878,8 @@ static int cifs_oplock_thread(void *dummyarg)
the call */
/* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping);
rc =
filemap_fdatawrite(inode->i_mapping);
if (CIFS_I(inode)->clientCanCacheRead
== 0) {
filemap_fdatawait(inode->i_mapping);
......@@ -907,8 +904,7 @@ static int cifs_oplock_thread(void *dummyarg)
0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE,
0 /* wait flag */);
cFYI(1,
("Oplock release rc = %d ", rc));
cFYI(1, ("Oplock release rc = %d", rc));
}
} else
spin_unlock(&GlobalMid_Lock);
......
/*
* fs/cifs/cifsfs.h
*
* Copyright (c) International Business Machines Corp., 2002, 2005
* Copyright (c) International Business Machines Corp., 2002, 2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
......@@ -99,7 +99,12 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
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,
extern int cifs_ioctl(struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.50"
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
#define CIFS_VERSION "1.51"
#endif /* _CIFSFS_H */
......@@ -19,6 +19,7 @@
#include <linux/in.h>
#include <linux/in6.h>
#include "cifs_fs_sb.h"
#include "cifsacl.h"
/*
* The sizes of various internal tables and strings
*/
......@@ -89,7 +90,8 @@ enum statusEnum {
};
enum securityEnum {
LANMAN = 0, /* Legacy LANMAN auth */
PLAINTXT = 0, /* Legacy with Plaintext passwords */
LANMAN, /* Legacy LANMAN auth */
NTLM, /* Legacy NTLM012 auth with NTLM hash */
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO */
......@@ -115,6 +117,17 @@ struct mac_key {
} data;
};
struct cifs_cred {
int uid;
int gid;
int mode;
int cecount;
struct cifs_sid osid;
struct cifs_sid gsid;
struct cifs_ntace *ntaces;
struct cifs_ace *aces;
};
/*
*****************************************************************
* Except the CIFS PDUs themselves all the
......@@ -279,6 +292,7 @@ struct cifsTconInfo {
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */
unsigned retry:1;
unsigned nocase:1;
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
......@@ -329,6 +343,7 @@ struct cifsFileInfo {
struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */
unsigned messageMode:1; /* for pipes: message vs byte mode */
atomic_t wrtPending; /* handle in use - defer close */
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
char *search_resume_name; /* BB removeme BB */
......@@ -464,6 +479,9 @@ struct dir_notify_req {
#ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MAY_LANMAN 0x00010
#define CIFSSEC_MAY_PLNTXT 0x00020
#else
#define CIFSSEC_MAY_LANMAN 0
#define CIFSSEC_MAY_PLNTXT 0
#endif /* weak passwords */
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
......@@ -477,14 +495,23 @@ require use of the stronger protocol */
#ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020
#ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
#else
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
#endif /* UPCALL */
#else /* do not allow weak pw hash */
#ifdef CONFIG_CIFS_UPCALL
#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */
#else
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */
#endif /* UPCALL */
#endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
/*
*****************************************************************
* All constants go here
......
......@@ -215,6 +215,12 @@
/* file_execute, file_read_attributes*/
/* write_dac, and delete. */
#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
| FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
/*
* Invalid readdir handle
*/
......@@ -360,10 +366,10 @@ struct smb_hdr {
__u8 WordCount;
} __attribute__((packed));
/* given a pointer to an smb_hdr retrieve the value of byte count */
#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
/*
* Computer Name Length (since Netbios name was length 16 with last byte 0x20)
......@@ -716,6 +722,14 @@ typedef struct smb_com_findclose_req {
#define REQ_OPENDIRONLY 0x00000008
#define REQ_EXTENDED_INFO 0x00000010
/* File type */
#define DISK_TYPE 0x0000
#define BYTE_PIPE_TYPE 0x0001
#define MESSAGE_PIPE_TYPE 0x0002
#define PRINTER_TYPE 0x0003
#define COMM_DEV_TYPE 0x0004
#define UNKNOWN_TYPE 0xFFFF
typedef struct smb_com_open_req { /* also handles create */
struct smb_hdr hdr; /* wct = 24 */
__u8 AndXCommand;
......
......@@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
int * /* bytes returned */ , const int long_op);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */ , const int long_op);
int * /* type of buf returned */ , const int long_op,
const int logError /* whether to log status code*/ );
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
struct cifsTconInfo *,
struct smb_hdr * /* input */ ,
......@@ -65,7 +66,7 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType);
extern int cifs_inet_pton(int, char *source, void *dst);
extern int map_smb_to_linux_error(struct smb_hdr *smb);
extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of
fixed section (word count) in two byte units */);
......@@ -304,12 +305,13 @@ extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
const char *pass);
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
const struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
const struct nls_table *);
#ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */
extern int parse_sec_desc(struct cifs_ntsd *, int);
extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon,
const char *fromName,
......
This diff is collapsed.
This diff is collapsed.
......@@ -3,7 +3,7 @@
*
* vfs operations that deal with dentries
*
* Copyright (C) International Business Machines Corp., 2002,2005
* Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
......@@ -269,7 +269,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
CIFSSMBClose(xid, pTcon, fileHandle);
} else if (newinode) {
pCifsFile =
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile == NULL)
goto cifs_create_out;
......@@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
/* BB Do not bother to decode buf since no
local inode yet to put timestamps in,
but we can reuse it safely */
int bytes_written;
unsigned int bytes_written;
struct win_dev *pdev;
pdev = (struct win_dev *)buf;
if (S_ISCHR(mode)) {
......@@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
xid = GetXid();
cFYI(1,
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p",
parent_dir_inode, direntry->d_name.name, direntry));
/* check whether path exists */
......
......@@ -43,6 +43,7 @@
#include <linux/exportfs.h>
#include "cifsglob.h"
#include "cifs_debug.h"
#include "cifsfs.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL
static struct dentry *cifs_get_parent(struct dentry *dentry)
......
......@@ -467,7 +467,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
int cifs_close(struct inode *inode, struct file *file)
{
int rc = 0;
int xid;
int xid, timeout;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pSMBFile =
......@@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file)
/* no sense reconnecting to close a file that is
already closed */
if (pTcon->tidStatus != CifsNeedReconnect) {
int timeout = 2;
timeout = 2;
while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout < 1000) ) {
&& (timeout <= 2048)) {
/* Give write a better chance to get to
server ahead of the close. We do not
want to add a wait_q here as it would
......@@ -522,12 +522,30 @@ int cifs_close(struct inode *inode, struct file *file)
list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist);
write_unlock(&GlobalSMBSeslock);
timeout = 10;
/* We waited above to give the SMBWrite a chance to issue
on the wire (so we do not get SMBWrite returning EBADF
if writepages is racing with close. Note that writepages
does not specify a file handle, so it is possible for a file
to be opened twice, and the application close the "wrong"
file handle - in these cases we delay long enough to allow
the SMBWrite to get on the wire before the SMB Close.
We allow total wait here over 45 seconds, more than
oplock break time, and more than enough to allow any write
to complete on the server, or to time out on the client */
while ((atomic_read(&pSMBFile->wrtPending) != 0)
&& (timeout <= 50000)) {
cERROR(1, ("writes pending, delay free of handle"));
msleep(timeout);
timeout *= 8;
}
kfree(pSMBFile->search_resume_name);
kfree(file->private_data);
file->private_data = NULL;
} else
rc = -EBADF;
read_lock(&GlobalSMBSeslock);
if (list_empty(&(CIFS_I(inode)->openFileList))) {
cFYI(1, ("closing last open instance for inode %p", inode));
/* if the file is not open we do not know if we can cache info
......@@ -535,6 +553,7 @@ int cifs_close(struct inode *inode, struct file *file)
CIFS_I(inode)->clientCanCacheRead = FALSE;
CIFS_I(inode)->clientCanCacheAll = FALSE;
}
read_unlock(&GlobalSMBSeslock);
if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
rc = CIFS_I(inode)->write_behind_rc;
FreeXid(xid);
......@@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
mutex_lock(&fid->lock_mutex);
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
if (pfLock->fl_start <= li->offset &&
length >= li->length) {
(pfLock->fl_start + length) >=
(li->offset + li->length)) {
stored_rc = CIFSSMBLock(xid, pTcon,
netfid,
li->length, li->offset,
......@@ -1022,6 +1042,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
}
read_lock(&GlobalSMBSeslock);
refind_writable:
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend)
continue;
......@@ -1029,24 +1050,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) {
atomic_inc(&open_file->wrtPending);
if (!open_file->invalidHandle) {
/* found a good writable file */
read_unlock(&GlobalSMBSeslock);
return open_file;
}
read_unlock(&GlobalSMBSeslock);
if ((open_file->invalidHandle) &&
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
rc = cifs_reopen_file(open_file->pfile, FALSE);
/* if it fails, try another handle - might be */
/* dangerous to hold up writepages with retry */
if (rc) {
cFYI(1,
("failed on reopen file in wp"));
/* Had to unlock since following call can block */
rc = cifs_reopen_file(open_file->pfile, FALSE);
if (!rc) {
if (!open_file->closePend)
return open_file;
else { /* start over in case this was deleted */
/* since the list could be modified */
read_lock(&GlobalSMBSeslock);
/* can not use this handle, no write
pending on this one after all */
atomic_dec
(&open_file->wrtPending);
continue;
atomic_dec(&open_file->wrtPending);
goto refind_writable;
}
}
return open_file;
/* if it fails, try another handle if possible -
(we can not do this if closePending since
loop could be modified - in which case we
have to start at the beginning of the list
again. Note that it would be bad
to hold up writepages here (rather than
in caller) with continuous retries */
cFYI(1, ("wp failed on reopen file"));
read_lock(&GlobalSMBSeslock);
/* can not use this handle, no write
pending on this one after all */
atomic_dec(&open_file->wrtPending);
if (open_file->closePend) /* list could have changed */
goto refind_writable;
/* else we simply continue to the next entry. Thus
we do not loop on reopen errors. If we
can not reopen the file, for example if we
reconnected to a server with another client
racing to delete or lock the file we would not
make progress if we restarted before the beginning
of the loop here. */
}
}
read_unlock(&GlobalSMBSeslock);
......@@ -1709,7 +1755,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
struct page *page;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int bytes_read = 0;
unsigned int bytes_read = 0;
unsigned int read_size, i;
char *smb_read_data = NULL;
struct smb_com_read_rsp *pSMBr;
......@@ -1803,7 +1849,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
i += bytes_read >> PAGE_CACHE_SHIFT;
cifs_stats_bytes_read(pTcon, bytes_read);
if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
i++; /* account for partial page */
/* server copy of file can have smaller size
......
......@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_mode = le64_to_cpu(findData.Permissions);
/* since we set the inode type below we need to mask off
to avoid strange results if bits set above */
inode->i_mode &= ~S_IFMT;
inode->i_mode &= ~S_IFMT;
if (type == UNIX_FILE) {
inode->i_mode |= S_IFREG;
} else if (type == UNIX_SYMLINK) {
......@@ -575,19 +575,33 @@ int cifs_get_inode_info(struct inode **pinode,
return rc;
}
static const struct inode_operations cifs_ipc_inode_ops = {
.lookup = cifs_lookup,
};
/* gets root inode */
void cifs_read_inode(struct inode *inode)
{
int xid;
int xid, rc;
struct cifs_sb_info *cifs_sb;
cifs_sb = CIFS_SB(inode->i_sb);
xid = GetXid();
if (cifs_sb->tcon->unix_ext)
cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
else
cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
if (rc && cifs_sb->tcon->ipc) {
cFYI(1, ("ipc connection - fake read inode"));
inode->i_mode |= S_IFDIR;
inode->i_nlink = 2;
inode->i_op = &cifs_ipc_inode_ops;
inode->i_fop = &simple_dir_operations;
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
}
/* can not call macro FreeXid here since in a void func */
_FreeXid(xid);
}
......@@ -919,18 +933,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
goto mkdir_out;
}
mode &= ~current->fs->umask;
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
mode, NULL /* netfid */, pInfo, &oplock,
full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
if (rc == -EOPNOTSUPP) {
kfree(pInfo);
goto mkdir_retry_old;
} else if (rc) {
cFYI(1, ("posix mkdir returned 0x%x", rc));
d_drop(direntry);
} else {
int obj_type;
if (pInfo->Type == -1) /* no return info - go query */
if (pInfo->Type == cpu_to_le32(-1)) {
/* no return info, go query for it */
kfree(pInfo);
goto mkdir_get_info;
}
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
to set uid/gid */
inc_nlink(inode);
......@@ -940,8 +961,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
direntry->d_op = &cifs_dentry_ops;
newinode = new_inode(inode->i_sb);
if (newinode == NULL)
if (newinode == NULL) {
kfree(pInfo);
goto mkdir_get_info;
}
/* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that
the server is really filling in that field? */
......@@ -972,7 +995,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
kfree(pInfo);
goto mkdir_out;
}
mkdir_retry_old:
/* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
......@@ -1377,8 +1400,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset)
}
i_size_write(inode, offset);
spin_unlock(&inode->i_lock);
/*
* unmap_mapping_range is called twice, first simply for efficiency
* so that truncate_inode_pages does fewer single-page unmaps. However
* after this first call, and before truncate_inode_pages finishes,
* it is possible for private pages to be COWed, which remain after
* truncate_inode_pages finishes, hence the second unmap_mapping_range
* call must be made for correctness.
*/
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset);
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
goto out_truncate;
do_expand:
......@@ -1469,7 +1501,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
atomic_dec(&open_file->wrtPending);
cFYI(1, ("SetFSize for attrs rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
int bytes_written;
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL,
......@@ -1502,7 +1534,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == 0) {
int bytes_written;
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
netfid, 0,
attrs->ia_size,
......
......@@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
char *tmp_path = NULL;
char *tmpbuffer;
unsigned char *referrals = NULL;
int num_referrals = 0;
unsigned int num_referrals = 0;
int len;
__u16 fid;
......
......@@ -169,7 +169,6 @@ cifs_buf_get(void)
void
cifs_buf_release(void *buf_to_free)
{
if (buf_to_free == NULL) {
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
return;
......
......@@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
{ERRusempx, -EIO},
{ERRusestd, -EIO},
{ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
{ERRaccountexpired, -EACCES},
{ERRnoSuchUser, -EACCES},
/* {ERRaccountexpired, -EACCES},
{ERRbadclient, -EACCES},
{ERRbadLogonTime, -EACCES},
{ERRpasswordExpired, -EACCES},
{ERRpasswordExpired, -EACCES},*/
{ERRaccountexpired, -EKEYEXPIRED},
{ERRbadclient, -EACCES},
{ERRbadLogonTime, -EACCES},
{ERRpasswordExpired, -EKEYEXPIRED},
{ERRnosupport, -EINVAL},
{0, 0}
};
......@@ -270,7 +276,7 @@ static const struct {
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
during the session setup } */
{
ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
......@@ -285,10 +291,10 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
......@@ -585,7 +591,7 @@ static const struct {
ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
......@@ -754,7 +760,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
}
int
map_smb_to_linux_error(struct smb_hdr *smb)
map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
{
unsigned int i;
int rc = -EIO; /* if transport error smb error may not be set */
......@@ -771,7 +777,9 @@ map_smb_to_linux_error(struct smb_hdr *smb)
/* translate the newer STATUS codes to old style SMB errors
* and then to POSIX errors */
__u32 err = le32_to_cpu(smb->Status.CifsError);
if (cifsFYI & CIFS_RC)
if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
cifs_print_status(err);
else if (cifsFYI & CIFS_RC)
cifs_print_status(err);
ntstatus_to_dos(err, &smberrclass, &smberrcode);
} else {
......@@ -813,7 +821,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
}
/* else ERRHRD class errors or junk - return EIO */
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!",
cFYI(1, ("Mapping smb error code %d to POSIX err %d",
smberrcode, rc));
/* generic corrective action e.g. reconnect SMB session on
......@@ -899,8 +907,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
cERROR(1, ("illegal hours %d", st->Hours));
days = sd->Day;
month = sd->Month;
if ((days > 31) || (month > 12))
if ((days > 31) || (month > 12)) {
cERROR(1, ("illegal date, month %d day: %d", month, days));
if (month > 12)
month = 12;
}
month -= 1;
days += total_days_of_prev_months[month];
days += 3652; /* account for difference in days between 1980 and 1970 */
......
......@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
char *buf, int *pobject_type, int isNewInode)
char *buf, unsigned int *pobject_type, int isNewInode)
{
loff_t local_size;
struct timespec local_mtime;
......@@ -294,7 +294,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
}
static void unix_fill_in_inode(struct inode *tmp_inode,
FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode)
FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode)
{
loff_t local_size;
struct timespec local_mtime;
......@@ -826,7 +826,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
int rc = 0;
struct qstr qstring;
struct cifsFileInfo *pCifsF;
unsigned obj_type;
unsigned int obj_type;
ino_t inum;
struct cifs_sb_info *cifs_sb;
struct inode *tmp_inode;
......@@ -1067,7 +1067,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if (current_entry == NULL) {
/* evaluate whether this case is an error */
cERROR(1,("past end of SMB num to fill %d i %d",
cERROR(1, ("past SMB end, num to fill %d i %d",
num_to_fill, i));
break;
}
......
......@@ -67,14 +67,59 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
capabilities |= CAP_DFS;
}
if (ses->capabilities & CAP_UNIX) {
if (ses->capabilities & CAP_UNIX)
capabilities |= CAP_UNIX;
}
/* BB check whether to init vcnum BB */
return capabilities;
}
static void
unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
{
char *bcc_ptr = *pbcc_area;
int bytes_ret = 0;
/* Copy OS version */
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
nls_cp);
bcc_ptr += 2 * bytes_ret;
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
*pbcc_area = bcc_ptr;
}
static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses,
const struct nls_table *nls_cp)
{
char *bcc_ptr = *pbcc_area;
int bytes_ret = 0;
/* copy domain */
if (ses->domainName == NULL) {
/* Sending null domain better than using a bogus domain name (as
we did briefly in 2.6.18) since server will use its default */
*bcc_ptr = 0;
*(bcc_ptr+1) = 0;
bytes_ret = 0;
} else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */
*pbcc_area = bcc_ptr;
}
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
const struct nls_table *nls_cp)
{
......@@ -100,32 +145,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
}
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null termination */
/* copy domain */
if (ses->domainName == NULL) {
/* Sending null domain better than using a bogus domain name (as
we did briefly in 2.6.18) since server will use its default */
*bcc_ptr = 0;
*(bcc_ptr+1) = 0;
bytes_ret = 0;
} else
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
256, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* account for null terminator */
/* Copy OS version */
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
nls_cp);
bcc_ptr += 2 * bytes_ret;
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
32, nls_cp);
bcc_ptr += 2 * bytes_ret;
bcc_ptr += 2; /* trailing null */
unicode_domain_string(&bcc_ptr, ses, nls_cp);
unicode_oslm_strings(&bcc_ptr, nls_cp);
*pbcc_area = bcc_ptr;
}
......@@ -203,14 +225,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len >= words_left)
return rc;
if (ses->serverOS)
kfree(ses->serverOS);
kfree(ses->serverOS);
/* UTF-8 string will not grow more than four times as big as UCS-16 */
ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
if (ses->serverOS != NULL) {
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
nls_cp);
}
if (ses->serverOS != NULL)
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
data += 2 * (len + 1);
words_left -= len + 1;
......@@ -220,8 +239,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len >= words_left)
return rc;
if (ses->serverNOS)
kfree(ses->serverNOS);
kfree(ses->serverNOS);
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
if (ses->serverNOS != NULL) {
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
......@@ -240,8 +258,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
if (len > words_left)
return rc;
if (ses->serverDomain)
kfree(ses->serverDomain);
kfree(ses->serverDomain);
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
if (ses->serverDomain != NULL) {
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
......@@ -271,8 +288,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
if (len >= bleft)
return rc;
if (ses->serverOS)
kfree(ses->serverOS);
kfree(ses->serverOS);
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
if (ses->serverOS)
......@@ -289,8 +305,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
if (len >= bleft)
return rc;
if (ses->serverNOS)
kfree(ses->serverNOS);
kfree(ses->serverNOS);
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
if (ses->serverNOS)
......@@ -479,7 +494,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
if (ses->capabilities & CAP_UNICODE) {
if (iov[0].iov_len % 2) {
*bcc_ptr = 0;
} bcc_ptr++;
bcc_ptr++;
}
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
......@@ -497,7 +513,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
iov[1].iov_base = str_area;
iov[1].iov_len = count;
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type,
0 /* not long op */, 1 /* log NT STATUS if any */ );
/* SMB request buf freed in SendReceive2 */
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
......
......@@ -173,9 +173,10 @@
#define ERRusestd 251 /* temporarily unable to use either raw
or mpx */
#define ERR_NOTIFY_ENUM_DIR 1024
#define ERRnoSuchUser 2238 /* user account does not exist */
#define ERRaccountexpired 2239
#define ERRbadclient 2240
#define ERRbadLogonTime 2241
#define ERRbadclient 2240 /* can not logon from this client */
#define ERRbadLogonTime 2241 /* logon hours do not allow this */
#define ERRpasswordExpired 2242
#define ERRnetlogonNotStarted 2455
#define ERRnosupport 0xFFFF
......@@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
if (temp == NULL)
return temp;
else {
memset(temp, 0, sizeof (struct mid_q_entry));
memset(temp, 0, sizeof(struct mid_q_entry));
temp->mid = smb_buffer->Mid; /* always LE */
temp->pid = current->pid;
temp->command = smb_buffer->Command;
......@@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
iov.iov_len = len;
smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof (struct sockaddr);
smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
......@@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
return -ENOTSOCK; /* BB eventually add reconnect code here */
smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof (struct sockaddr);
smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
......@@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
} /* else ok - we are setting up session */
}
*ppmidQ = AllocMidQEntry(in_buf, ses);
if (*ppmidQ == NULL) {
if (*ppmidQ == NULL)
return -ENOMEM;
}
return 0;
}
......@@ -419,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
int
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
const int long_op)
const int long_op, const int logError)
{
int rc = 0;
unsigned int receive_len;
......@@ -465,7 +464,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
wake_up(&ses->server->request_q);
return rc;
}
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED;
......@@ -568,13 +566,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
}
/* BB special case reconnect tid and uid here? */
/* BB special case Errbadpassword and pwdexpired here */
rc = map_smb_to_linux_error(midQ->resp_buf);
rc = map_smb_to_linux_error(midQ->resp_buf, logError);
/* convert ByteCount if necessary */
if (receive_len >=
sizeof (struct smb_hdr) -
4 /* do not count RFC1001 header */ +
if (receive_len >= sizeof(struct smb_hdr) - 4
/* do not count RFC1001 header */ +
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
BCC(midQ->resp_buf) =
le16_to_cpu(BCC_LE(midQ->resp_buf));
......@@ -749,12 +745,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
*pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and uid here? */
rc = map_smb_to_linux_error(out_buf);
rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
/* convert ByteCount if necessary */
if (receive_len >=
sizeof (struct smb_hdr) -
4 /* do not count RFC1001 header */ +
if (receive_len >= sizeof(struct smb_hdr) - 4
/* do not count RFC1001 header */ +
(2 * out_buf->WordCount) + 2 /* bcc */ )
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else {
......@@ -993,12 +988,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
*pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and uid here? */
rc = map_smb_to_linux_error(out_buf);
rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
/* convert ByteCount if necessary */
if (receive_len >=
sizeof (struct smb_hdr) -
4 /* do not count RFC1001 header */ +
if (receive_len >= sizeof(struct smb_hdr) - 4
/* do not count RFC1001 header */ +
(2 * out_buf->WordCount) + 2 /* bcc */ )
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else {
......
......@@ -261,21 +261,26 @@ 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) {
#ifdef CONFIG_CIFS_EXPERIMENTAL
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 (experimEnabled)
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);
/* else rc is EOPNOTSUPP from above */
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 */
}
#endif /* EXPERIMENTAL */
#else
cFYI(1, ("query POSIX ACL not supported yet"));
#endif /* CONFIG_CIFS_POSIX */
......
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