mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-13 01:08:50 +00:00
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 ...
This commit is contained in:
commit
2843483d2e
@ -1,3 +1,19 @@
|
|||||||
|
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
|
Version 1.50
|
||||||
------------
|
------------
|
||||||
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
|
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"
|
Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix"
|
||||||
mount option to allow disabling the CIFS Unix Extensions for just
|
mount option to allow disabling the CIFS Unix Extensions for just
|
||||||
that mount. Fix hang on spinlock in find_writable_file (race when
|
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
|
Version 1.49
|
||||||
------------
|
------------
|
||||||
|
@ -3,4 +3,4 @@
|
|||||||
#
|
#
|
||||||
obj-$(CONFIG_CIFS) += cifs.o
|
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;
|
unsigned long *optr;
|
||||||
|
|
||||||
size = eoc - ctx->pointer + 1;
|
size = eoc - ctx->pointer + 1;
|
||||||
*oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
|
*oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
|
||||||
if (*oid == NULL) {
|
if (*oid == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
optr = *oid;
|
optr = *oid;
|
||||||
|
|
||||||
@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
|||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||||
|| (tag != ASN1_SEQ)) {
|
|| (tag != ASN1_SEQ)) {
|
||||||
cFYI(1,
|
cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
|
||||||
("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
|
cls, con, tag, end, *end));
|
||||||
cls, con, tag, end, *end));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
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++;
|
i++;
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
||||||
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
||||||
length =
|
length = sprintf(buf, "\n%d) %s Uses: %d ", i,
|
||||||
sprintf(buf,
|
tcon->treeName, atomic_read(&tcon->useCount));
|
||||||
"\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
|
buf += length;
|
||||||
"Attributes: 0x%x\nPathComponentMax: %d Status: %d",
|
if (tcon->nativeFileSystem) {
|
||||||
i, tcon->treeName,
|
length = sprintf(buf, "Type: %s ",
|
||||||
atomic_read(&tcon->useCount),
|
tcon->nativeFileSystem);
|
||||||
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->fsDevInfo.DeviceCharacteristics),
|
||||||
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
||||||
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
||||||
@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer,
|
|||||||
if (count < 3) {
|
if (count < 3) {
|
||||||
/* single char or single char followed by null */
|
/* single char or single char followed by null */
|
||||||
c = flags_string[0];
|
c = flags_string[0];
|
||||||
if (c == '0' || c == 'n' || c == 'N')
|
if (c == '0' || c == 'n' || c == 'N') {
|
||||||
extended_security = CIFSSEC_DEF; /* default */
|
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;
|
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 */
|
/* else we have a number */
|
||||||
|
|
||||||
|
333
fs/cifs/cifsacl.c
Normal file
333
fs/cifs/cifsacl.c
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/*
|
||||||
|
* 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 */
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* fs/cifs/cifsacl.h
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
@ -22,17 +22,65 @@
|
|||||||
#ifndef _CIFSACL_H
|
#ifndef _CIFSACL_H
|
||||||
#define _CIFSACL_H
|
#define _CIFSACL_H
|
||||||
|
|
||||||
struct cifs_sid {
|
|
||||||
__u8 revision; /* revision level */
|
#define NUM_AUTHS 6 /* number of authority fields */
|
||||||
__u8 num_subauths;
|
#define NUM_SUBAUTHS 5 /* number of sub authority fields */
|
||||||
__u8 authority[6];
|
#define NUM_WK_SIDS 7 /* number of well known sids */
|
||||||
__u32 sub_auth[4];
|
#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
|
||||||
/* next sub_auth if any ... */
|
|
||||||
|
#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));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* everyone */
|
struct cifs_sid {
|
||||||
/* extern const struct cifs_sid sid_everyone;*/
|
__u8 revision; /* revision level */
|
||||||
/* group users */
|
__u8 num_subauth;
|
||||||
/* extern const struct cifs_sid sid_user;*/
|
__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];
|
||||||
|
__le32 sub_auth[5];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
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 */
|
#endif /* _CIFSACL_H */
|
||||||
|
@ -345,7 +345,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
|||||||
user = kmalloc(2 + (len * 2), GFP_KERNEL);
|
user = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||||
if (user == NULL)
|
if (user == NULL)
|
||||||
goto calc_exit_2;
|
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);
|
UniStrupr(user);
|
||||||
hmac_md5_update((char *)user, 2*len, pctxt);
|
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);
|
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||||
if (domain == NULL)
|
if (domain == NULL)
|
||||||
goto calc_exit_1;
|
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
|
/* the following line was removed since it didn't work well
|
||||||
with lower cased domain name that passed as an option.
|
with lower cased domain name that passed as an option.
|
||||||
Maybe converting the domain name earlier makes sense */
|
Maybe converting the domain name earlier makes sense */
|
||||||
|
@ -49,10 +49,6 @@
|
|||||||
static struct quotactl_ops cifs_quotactl_ops;
|
static struct quotactl_ops cifs_quotactl_ops;
|
||||||
#endif /* QUOTA */
|
#endif /* QUOTA */
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
extern struct export_operations cifs_export_ops;
|
|
||||||
#endif /* EXPERIMENTAL */
|
|
||||||
|
|
||||||
int cifsFYI = 0;
|
int cifsFYI = 0;
|
||||||
int cifsERROR = 1;
|
int cifsERROR = 1;
|
||||||
int traceSMB = 0;
|
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);
|
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;
|
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
|
on the client (above and beyond ACL on servers) for
|
||||||
servers which do not support setting and viewing mode bits,
|
servers which do not support setting and viewing mode bits,
|
||||||
so allowing client to check permissions is useful */
|
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",
|
seq_printf(s, ",domain=%s",
|
||||||
cifs_sb->tcon->ses->domainName);
|
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)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||||
seq_printf(s, ",posixpaths");
|
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, ",rsize=%d", cifs_sb->rsize);
|
||||||
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
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) {
|
if (pTcon) {
|
||||||
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
|
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
|
||||||
} else {
|
} else {
|
||||||
return -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
@ -716,7 +712,7 @@ static int
|
|||||||
cifs_init_inodecache(void)
|
cifs_init_inodecache(void)
|
||||||
{
|
{
|
||||||
cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
|
cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
|
||||||
sizeof (struct cifsInodeInfo),
|
sizeof(struct cifsInodeInfo),
|
||||||
0, (SLAB_RECLAIM_ACCOUNT|
|
0, (SLAB_RECLAIM_ACCOUNT|
|
||||||
SLAB_MEM_SPREAD),
|
SLAB_MEM_SPREAD),
|
||||||
cifs_init_once);
|
cifs_init_once);
|
||||||
@ -816,8 +812,8 @@ static int
|
|||||||
cifs_init_mids(void)
|
cifs_init_mids(void)
|
||||||
{
|
{
|
||||||
cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
|
cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
|
||||||
sizeof (struct mid_q_entry), 0,
|
sizeof(struct mid_q_entry), 0,
|
||||||
SLAB_HWCACHE_ALIGN, NULL);
|
SLAB_HWCACHE_ALIGN, NULL);
|
||||||
if (cifs_mid_cachep == NULL)
|
if (cifs_mid_cachep == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -829,8 +825,8 @@ cifs_init_mids(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
|
cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
|
||||||
sizeof (struct oplock_q_entry), 0,
|
sizeof(struct oplock_q_entry), 0,
|
||||||
SLAB_HWCACHE_ALIGN, NULL);
|
SLAB_HWCACHE_ALIGN, NULL);
|
||||||
if (cifs_oplock_cachep == NULL) {
|
if (cifs_oplock_cachep == NULL) {
|
||||||
mempool_destroy(cifs_mid_poolp);
|
mempool_destroy(cifs_mid_poolp);
|
||||||
kmem_cache_destroy(cifs_mid_cachep);
|
kmem_cache_destroy(cifs_mid_cachep);
|
||||||
@ -882,7 +878,8 @@ static int cifs_oplock_thread(void *dummyarg)
|
|||||||
the call */
|
the call */
|
||||||
/* mutex_lock(&inode->i_mutex);*/
|
/* mutex_lock(&inode->i_mutex);*/
|
||||||
if (S_ISREG(inode->i_mode)) {
|
if (S_ISREG(inode->i_mode)) {
|
||||||
rc = filemap_fdatawrite(inode->i_mapping);
|
rc =
|
||||||
|
filemap_fdatawrite(inode->i_mapping);
|
||||||
if (CIFS_I(inode)->clientCanCacheRead
|
if (CIFS_I(inode)->clientCanCacheRead
|
||||||
== 0) {
|
== 0) {
|
||||||
filemap_fdatawait(inode->i_mapping);
|
filemap_fdatawait(inode->i_mapping);
|
||||||
@ -907,8 +904,7 @@ static int cifs_oplock_thread(void *dummyarg)
|
|||||||
0 /* len */ , 0 /* offset */, 0,
|
0 /* len */ , 0 /* offset */, 0,
|
||||||
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
||||||
0 /* wait flag */);
|
0 /* wait flag */);
|
||||||
cFYI(1,
|
cFYI(1, ("Oplock release rc = %d", rc));
|
||||||
("Oplock release rc = %d ", rc));
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* fs/cifs/cifsfs.h
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* 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);
|
size_t, int);
|
||||||
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||||
extern ssize_t cifs_listxattr(struct dentry *, char *, 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);
|
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 */
|
#endif /* _CIFSFS_H */
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <linux/in.h>
|
#include <linux/in.h>
|
||||||
#include <linux/in6.h>
|
#include <linux/in6.h>
|
||||||
#include "cifs_fs_sb.h"
|
#include "cifs_fs_sb.h"
|
||||||
|
#include "cifsacl.h"
|
||||||
/*
|
/*
|
||||||
* The sizes of various internal tables and strings
|
* The sizes of various internal tables and strings
|
||||||
*/
|
*/
|
||||||
@ -89,7 +90,8 @@ enum statusEnum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum securityEnum {
|
enum securityEnum {
|
||||||
LANMAN = 0, /* Legacy LANMAN auth */
|
PLAINTXT = 0, /* Legacy with Plaintext passwords */
|
||||||
|
LANMAN, /* Legacy LANMAN auth */
|
||||||
NTLM, /* Legacy NTLM012 auth with NTLM hash */
|
NTLM, /* Legacy NTLM012 auth with NTLM hash */
|
||||||
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
|
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
|
||||||
RawNTLMSSP, /* NTLMSSP without SPNEGO */
|
RawNTLMSSP, /* NTLMSSP without SPNEGO */
|
||||||
@ -115,6 +117,17 @@ struct mac_key {
|
|||||||
} data;
|
} 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
|
* Except the CIFS PDUs themselves all the
|
||||||
@ -279,6 +292,7 @@ struct cifsTconInfo {
|
|||||||
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
|
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
|
||||||
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
|
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
|
||||||
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
||||||
|
unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */
|
||||||
unsigned retry:1;
|
unsigned retry:1;
|
||||||
unsigned nocase:1;
|
unsigned nocase:1;
|
||||||
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
|
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. */
|
struct list_head llist; /* list of byte range locks we have. */
|
||||||
unsigned closePend:1; /* file is marked to close */
|
unsigned closePend:1; /* file is marked to close */
|
||||||
unsigned invalidHandle:1; /* file closed via session abend */
|
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 */
|
atomic_t wrtPending; /* handle in use - defer close */
|
||||||
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
|
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
|
||||||
char *search_resume_name; /* BB removeme BB */
|
char *search_resume_name; /* BB removeme BB */
|
||||||
@ -464,6 +479,9 @@ struct dir_notify_req {
|
|||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
#define CIFSSEC_MAY_LANMAN 0x00010
|
#define CIFSSEC_MAY_LANMAN 0x00010
|
||||||
#define CIFSSEC_MAY_PLNTXT 0x00020
|
#define CIFSSEC_MAY_PLNTXT 0x00020
|
||||||
|
#else
|
||||||
|
#define CIFSSEC_MAY_LANMAN 0
|
||||||
|
#define CIFSSEC_MAY_PLNTXT 0
|
||||||
#endif /* weak passwords */
|
#endif /* weak passwords */
|
||||||
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
|
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
|
||||||
|
|
||||||
@ -477,14 +495,23 @@ require use of the stronger protocol */
|
|||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
#define CIFSSEC_MUST_LANMAN 0x10010
|
#define CIFSSEC_MUST_LANMAN 0x10010
|
||||||
#define CIFSSEC_MUST_PLNTXT 0x20020
|
#define CIFSSEC_MUST_PLNTXT 0x20020
|
||||||
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
|
#ifdef CONFIG_CIFS_UPCALL
|
||||||
|
#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
|
||||||
#else
|
#else
|
||||||
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
|
#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 allowed */
|
||||||
|
#endif /* UPCALL */
|
||||||
#endif /* WEAK_PW_HASH */
|
#endif /* WEAK_PW_HASH */
|
||||||
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
|
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
|
||||||
|
|
||||||
#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
|
#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
|
||||||
#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_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
|
* All constants go here
|
||||||
|
@ -215,6 +215,12 @@
|
|||||||
/* file_execute, file_read_attributes*/
|
/* file_execute, file_read_attributes*/
|
||||||
/* write_dac, and delete. */
|
/* 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
|
* Invalid readdir handle
|
||||||
*/
|
*/
|
||||||
@ -360,10 +366,10 @@ struct smb_hdr {
|
|||||||
__u8 WordCount;
|
__u8 WordCount;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
/* given a pointer to an smb_hdr retrieve the value of byte count */
|
/* 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(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_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 */
|
/* 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)
|
* 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_OPENDIRONLY 0x00000008
|
||||||
#define REQ_EXTENDED_INFO 0x00000010
|
#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 */
|
typedef struct smb_com_open_req { /* also handles create */
|
||||||
struct smb_hdr hdr; /* wct = 24 */
|
struct smb_hdr hdr; /* wct = 24 */
|
||||||
__u8 AndXCommand;
|
__u8 AndXCommand;
|
||||||
|
@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
|
|||||||
int * /* bytes returned */ , const int long_op);
|
int * /* bytes returned */ , const int long_op);
|
||||||
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
|
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
|
||||||
struct kvec *, int /* nvec to send */,
|
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 */ ,
|
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
|
||||||
struct cifsTconInfo *,
|
struct cifsTconInfo *,
|
||||||
struct smb_hdr * /* input */ ,
|
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,
|
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
enum securityEnum *secType);
|
enum securityEnum *secType);
|
||||||
extern int cifs_inet_pton(int, char *source, void *dst);
|
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 */ ,
|
extern void header_assemble(struct smb_hdr *, char /* command */ ,
|
||||||
const struct cifsTconInfo *, int /* length of
|
const struct cifsTconInfo *, int /* length of
|
||||||
fixed section (word count) in two byte units */);
|
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);
|
const char *pass);
|
||||||
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
||||||
const struct nls_table *);
|
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 *,
|
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
|
||||||
const struct nls_table *);
|
const struct nls_table *);
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
|
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
|
||||||
#endif /* CIFS_WEAK_PW_HASH */
|
#endif /* CIFS_WEAK_PW_HASH */
|
||||||
|
extern int parse_sec_desc(struct cifs_ntsd *, int);
|
||||||
extern int CIFSSMBCopy(int xid,
|
extern int CIFSSMBCopy(int xid,
|
||||||
struct cifsTconInfo *source_tcon,
|
struct cifsTconInfo *source_tcon,
|
||||||
const char *fromName,
|
const char *fromName,
|
||||||
|
@ -34,10 +34,10 @@
|
|||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include "cifspdu.h"
|
#include "cifspdu.h"
|
||||||
#include "cifsglob.h"
|
#include "cifsglob.h"
|
||||||
|
#include "cifsacl.h"
|
||||||
#include "cifsproto.h"
|
#include "cifsproto.h"
|
||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "cifsacl.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
static struct {
|
static struct {
|
||||||
@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
|
|||||||
write_lock(&GlobalSMBSeslock);
|
write_lock(&GlobalSMBSeslock);
|
||||||
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
|
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
|
||||||
open_file = list_entry(tmp, struct cifsFileInfo, tlist);
|
open_file = list_entry(tmp, struct cifsFileInfo, tlist);
|
||||||
if (open_file) {
|
if (open_file)
|
||||||
open_file->invalidHandle = TRUE;
|
open_file->invalidHandle = TRUE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
write_unlock(&GlobalSMBSeslock);
|
write_unlock(&GlobalSMBSeslock);
|
||||||
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
|
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
|
||||||
@ -439,8 +438,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||||||
|
|
||||||
pSMB->hdr.Mid = GetNextMid(server);
|
pSMB->hdr.Mid = GetNextMid(server);
|
||||||
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
|
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
|
||||||
|
|
||||||
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
|
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
|
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
|
||||||
|
cFYI(1, ("Kerberos only mechanism, enable extended security"));
|
||||||
|
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
for (i = 0; i < CIFS_NUM_PROT; i++) {
|
for (i = 0; i < CIFS_NUM_PROT; i++) {
|
||||||
@ -513,7 +517,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||||||
(int)ts.tv_sec, (int)utc.tv_sec,
|
(int)ts.tv_sec, (int)utc.tv_sec,
|
||||||
(int)(utc.tv_sec - ts.tv_sec)));
|
(int)(utc.tv_sec - ts.tv_sec)));
|
||||||
val = (int)(utc.tv_sec - ts.tv_sec);
|
val = (int)(utc.tv_sec - ts.tv_sec);
|
||||||
seconds = val < 0 ? -val : val;
|
seconds = abs(val);
|
||||||
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
|
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
|
||||||
remain = seconds % MIN_TZ_ADJ;
|
remain = seconds % MIN_TZ_ADJ;
|
||||||
if (remain >= (MIN_TZ_ADJ / 2))
|
if (remain >= (MIN_TZ_ADJ / 2))
|
||||||
@ -574,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||||||
server->secType = NTLM;
|
server->secType = NTLM;
|
||||||
else if (secFlags & CIFSSEC_MAY_NTLMV2)
|
else if (secFlags & CIFSSEC_MAY_NTLMV2)
|
||||||
server->secType = NTLMv2;
|
server->secType = NTLMv2;
|
||||||
/* else krb5 ... any others ... */
|
else if (secFlags & CIFSSEC_MAY_KRB5)
|
||||||
|
server->secType = Kerberos;
|
||||||
|
else if (secFlags & CIFSSEC_MAY_LANMAN)
|
||||||
|
server->secType = LANMAN;
|
||||||
|
/* #ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
else if (secFlags & CIFSSEC_MAY_PLNTXT)
|
||||||
|
server->secType = ??
|
||||||
|
#endif */
|
||||||
|
else {
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
cERROR(1, ("Invalid security type"));
|
||||||
|
goto neg_err_exit;
|
||||||
|
}
|
||||||
|
/* else ... any others ...? */
|
||||||
|
|
||||||
/* one byte, so no need to convert this or EncryptionKeyLen from
|
/* one byte, so no need to convert this or EncryptionKeyLen from
|
||||||
little endian */
|
little endian */
|
||||||
@ -604,22 +621,26 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
|||||||
if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
|
if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
|
||||||
(server->capabilities & CAP_EXTENDED_SECURITY)) {
|
(server->capabilities & CAP_EXTENDED_SECURITY)) {
|
||||||
count = pSMBr->ByteCount;
|
count = pSMBr->ByteCount;
|
||||||
if (count < 16)
|
if (count < 16) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
else if (count == 16) {
|
goto neg_err_exit;
|
||||||
server->secType = RawNTLMSSP;
|
}
|
||||||
if (server->socketUseCount.counter > 1) {
|
|
||||||
if (memcmp(server->server_GUID,
|
if (server->socketUseCount.counter > 1) {
|
||||||
pSMBr->u.extended_response.
|
if (memcmp(server->server_GUID,
|
||||||
GUID, 16) != 0) {
|
pSMBr->u.extended_response.
|
||||||
cFYI(1, ("server UID changed"));
|
GUID, 16) != 0) {
|
||||||
memcpy(server->server_GUID,
|
cFYI(1, ("server UID changed"));
|
||||||
pSMBr->u.extended_response.GUID,
|
|
||||||
16);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
memcpy(server->server_GUID,
|
memcpy(server->server_GUID,
|
||||||
pSMBr->u.extended_response.GUID, 16);
|
pSMBr->u.extended_response.GUID,
|
||||||
|
16);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
memcpy(server->server_GUID,
|
||||||
|
pSMBr->u.extended_response.GUID, 16);
|
||||||
|
|
||||||
|
if (count == 16) {
|
||||||
|
server->secType = RawNTLMSSP;
|
||||||
} else {
|
} else {
|
||||||
rc = decode_negTokenInit(pSMBr->u.extended_response.
|
rc = decode_negTokenInit(pSMBr->u.extended_response.
|
||||||
SecurityBlob,
|
SecurityBlob,
|
||||||
@ -642,10 +663,12 @@ signing_check:
|
|||||||
/* MUST_SIGN already includes the MAY_SIGN FLAG
|
/* MUST_SIGN already includes the MAY_SIGN FLAG
|
||||||
so if this is zero it means that signing is disabled */
|
so if this is zero it means that signing is disabled */
|
||||||
cFYI(1, ("Signing disabled"));
|
cFYI(1, ("Signing disabled"));
|
||||||
if (server->secMode & SECMODE_SIGN_REQUIRED)
|
if (server->secMode & SECMODE_SIGN_REQUIRED) {
|
||||||
cERROR(1, ("Server requires "
|
cERROR(1, ("Server requires "
|
||||||
"/proc/fs/cifs/PacketSigningEnabled "
|
"packet signing to be enabled in "
|
||||||
"to be on"));
|
"/proc/fs/cifs/SecurityFlags."));
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
}
|
||||||
server->secMode &=
|
server->secMode &=
|
||||||
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
|
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
|
||||||
} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
|
} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
|
||||||
@ -1052,7 +1075,7 @@ PsxCreat:
|
|||||||
InformationLevel) - 4;
|
InformationLevel) - 4;
|
||||||
offset = param_offset + params;
|
offset = param_offset + params;
|
||||||
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
|
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
|
||||||
pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
|
pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
|
||||||
pdata->Permissions = cpu_to_le64(mode);
|
pdata->Permissions = cpu_to_le64(mode);
|
||||||
pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
|
pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
|
||||||
pdata->OpenFlags = cpu_to_le32(*pOplock);
|
pdata->OpenFlags = cpu_to_le32(*pOplock);
|
||||||
@ -1098,8 +1121,8 @@ PsxCreat:
|
|||||||
if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
|
if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
|
||||||
*pOplock |= CIFS_CREATE_ACTION;
|
*pOplock |= CIFS_CREATE_ACTION;
|
||||||
/* check to make sure response data is there */
|
/* check to make sure response data is there */
|
||||||
if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
|
if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
|
||||||
pRetData->Type = -1; /* unknown */
|
pRetData->Type = cpu_to_le32(-1); /* unknown */
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
cFYI(1, ("unknown type"));
|
cFYI(1, ("unknown type"));
|
||||||
#endif
|
#endif
|
||||||
@ -1107,12 +1130,12 @@ PsxCreat:
|
|||||||
if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
|
if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
|
||||||
+ sizeof(FILE_UNIX_BASIC_INFO)) {
|
+ sizeof(FILE_UNIX_BASIC_INFO)) {
|
||||||
cERROR(1, ("Open response data too small"));
|
cERROR(1, ("Open response data too small"));
|
||||||
pRetData->Type = -1;
|
pRetData->Type = cpu_to_le32(-1);
|
||||||
goto psx_create_err;
|
goto psx_create_err;
|
||||||
}
|
}
|
||||||
memcpy((char *) pRetData,
|
memcpy((char *) pRetData,
|
||||||
(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
|
(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
|
||||||
sizeof (FILE_UNIX_BASIC_INFO));
|
sizeof(FILE_UNIX_BASIC_INFO));
|
||||||
}
|
}
|
||||||
|
|
||||||
psx_create_err:
|
psx_create_err:
|
||||||
@ -1193,9 +1216,9 @@ OldOpenRetry:
|
|||||||
}
|
}
|
||||||
if (*pOplock & REQ_OPLOCK)
|
if (*pOplock & REQ_OPLOCK)
|
||||||
pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
|
pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
|
||||||
else if (*pOplock & REQ_BATCHOPLOCK) {
|
else if (*pOplock & REQ_BATCHOPLOCK)
|
||||||
pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
|
pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
|
||||||
}
|
|
||||||
pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
|
pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
|
||||||
/* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
|
/* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
|
||||||
/* 0 = read
|
/* 0 = read
|
||||||
@ -1310,9 +1333,8 @@ openRetry:
|
|||||||
}
|
}
|
||||||
if (*pOplock & REQ_OPLOCK)
|
if (*pOplock & REQ_OPLOCK)
|
||||||
pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
|
pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
|
||||||
else if (*pOplock & REQ_BATCHOPLOCK) {
|
else if (*pOplock & REQ_BATCHOPLOCK)
|
||||||
pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
|
pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
|
||||||
}
|
|
||||||
pSMB->DesiredAccess = cpu_to_le32(access_flags);
|
pSMB->DesiredAccess = cpu_to_le32(access_flags);
|
||||||
pSMB->AllocationSize = 0;
|
pSMB->AllocationSize = 0;
|
||||||
/* set file as system file if special file such
|
/* set file as system file if special file such
|
||||||
@ -1424,9 +1446,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
|
|||||||
|
|
||||||
iov[0].iov_base = (char *)pSMB;
|
iov[0].iov_base = (char *)pSMB;
|
||||||
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
|
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
|
||||||
rc = SendReceive2(xid, tcon->ses, iov,
|
rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
|
||||||
1 /* num iovecs */,
|
&resp_buf_type, 0 /* not long op */, 1 /* log err */ );
|
||||||
&resp_buf_type, 0);
|
|
||||||
cifs_stats_inc(&tcon->num_reads);
|
cifs_stats_inc(&tcon->num_reads);
|
||||||
pSMBr = (READ_RSP *)iov[0].iov_base;
|
pSMBr = (READ_RSP *)iov[0].iov_base;
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@ -1446,11 +1467,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
|
|||||||
*nbytes = 0;
|
*nbytes = 0;
|
||||||
} else {
|
} else {
|
||||||
pReadData = (char *) (&pSMBr->hdr.Protocol) +
|
pReadData = (char *) (&pSMBr->hdr.Protocol) +
|
||||||
le16_to_cpu(pSMBr->DataOffset);
|
le16_to_cpu(pSMBr->DataOffset);
|
||||||
/* if (rc = copy_to_user(buf, pReadData, data_length)) {
|
/* if (rc = copy_to_user(buf, pReadData, data_length)) {
|
||||||
cERROR(1,("Faulting on read rc = %d",rc));
|
cERROR(1,("Faulting on read rc = %d",rc));
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
}*/ /* can not use copy_to_user when using page cache*/
|
}*/ /* can not use copy_to_user when using page cache*/
|
||||||
if (*buf)
|
if (*buf)
|
||||||
memcpy(*buf, pReadData, data_length);
|
memcpy(*buf, pReadData, data_length);
|
||||||
}
|
}
|
||||||
@ -1645,7 +1666,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
|||||||
|
|
||||||
|
|
||||||
rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
|
rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
|
||||||
long_op);
|
long_op, 0 /* do not log STATUS code */ );
|
||||||
cifs_stats_inc(&tcon->num_writes);
|
cifs_stats_inc(&tcon->num_writes);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, ("Send error Write2 = %d", rc));
|
cFYI(1, ("Send error Write2 = %d", rc));
|
||||||
@ -2538,7 +2559,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
|
|||||||
cFYI(1, ("data starts after end of smb"));
|
cFYI(1, ("data starts after end of smb"));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if (data_count + *ppdata > end_of_smb) {
|
} else if (data_count + *ppdata > end_of_smb) {
|
||||||
cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
|
cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
|
||||||
*ppdata, data_count, (data_count + *ppdata),
|
*ppdata, data_count, (data_count + *ppdata),
|
||||||
end_of_smb, pSMBr));
|
end_of_smb, pSMBr));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -2615,7 +2636,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
|||||||
reparse_buf->TargetNameOffset +
|
reparse_buf->TargetNameOffset +
|
||||||
reparse_buf->TargetNameLen) >
|
reparse_buf->TargetNameLen) >
|
||||||
end_of_smb) {
|
end_of_smb) {
|
||||||
cFYI(1,("reparse buf goes beyond SMB"));
|
cFYI(1, ("reparse buf beyond SMB"));
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
goto qreparse_out;
|
goto qreparse_out;
|
||||||
}
|
}
|
||||||
@ -3042,25 +3063,12 @@ GetExtAttrOut:
|
|||||||
|
|
||||||
#endif /* CONFIG_POSIX */
|
#endif /* CONFIG_POSIX */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
/* security id for everyone */
|
|
||||||
static const struct cifs_sid sid_everyone =
|
|
||||||
{1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
|
|
||||||
/* group users */
|
|
||||||
static 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 */
|
/* Get Security Descriptor (by handle) from remote server for a file or dir */
|
||||||
int
|
int
|
||||||
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
||||||
/* BB fix up return info */ char *acl_inf, const int buflen,
|
/* BB fix up return info */ char *acl_inf, const int buflen,
|
||||||
const int acl_type /* ACCESS/DEFAULT not sure implication */)
|
const int acl_type)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int buf_type = 0;
|
int buf_type = 0;
|
||||||
@ -3085,12 +3093,13 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
|||||||
iov[0].iov_base = (char *)pSMB;
|
iov[0].iov_base = (char *)pSMB;
|
||||||
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
|
iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
|
||||||
|
|
||||||
rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
|
rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
|
||||||
|
0 /* not long op */, 0 /* do not log STATUS codes */ );
|
||||||
cifs_stats_inc(&tcon->num_acl_get);
|
cifs_stats_inc(&tcon->num_acl_get);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, ("Send error in QuerySecDesc = %d", rc));
|
cFYI(1, ("Send error in QuerySecDesc = %d", rc));
|
||||||
} else { /* decode response */
|
} else { /* decode response */
|
||||||
struct cifs_sid *psec_desc;
|
struct cifs_ntsd *psec_desc;
|
||||||
__le32 * parm;
|
__le32 * parm;
|
||||||
int parm_len;
|
int parm_len;
|
||||||
int data_len;
|
int data_len;
|
||||||
@ -3105,8 +3114,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
|||||||
goto qsec_out;
|
goto qsec_out;
|
||||||
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
|
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
|
||||||
|
|
||||||
cERROR(1, ("smb %p parm %p data %p",
|
cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
|
||||||
pSMBr, parm, psec_desc)); /* BB removeme BB */
|
|
||||||
|
|
||||||
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
|
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
|
||||||
rc = -EIO; /* bad smb */
|
rc = -EIO; /* bad smb */
|
||||||
@ -3115,7 +3123,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
|||||||
|
|
||||||
/* BB check that data area is minimum length and as big as acl_len */
|
/* BB check that data area is minimum length and as big as acl_len */
|
||||||
|
|
||||||
acl_len = le32_to_cpu(*(__le32 *)parm);
|
acl_len = le32_to_cpu(*parm);
|
||||||
/* BB check if (acl_len > bufsize) */
|
/* BB check if (acl_len > bufsize) */
|
||||||
|
|
||||||
parse_sec_desc(psec_desc, acl_len);
|
parse_sec_desc(psec_desc, acl_len);
|
||||||
@ -3128,6 +3136,7 @@ qsec_out:
|
|||||||
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
|
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||||
|
|
||||||
/* Legacy Query Path Information call for lookup to old servers such
|
/* Legacy Query Path Information call for lookup to old servers such
|
||||||
as Win9x/WinME */
|
as Win9x/WinME */
|
||||||
@ -3363,6 +3372,9 @@ UnixQPathInfoRetry:
|
|||||||
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
||||||
|
|
||||||
if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
|
if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
|
||||||
|
cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
|
||||||
|
"Unix Extensions can be disabled on mount "
|
||||||
|
"by specifying the nosfu mount option."));
|
||||||
rc = -EIO; /* bad smb */
|
rc = -EIO; /* bad smb */
|
||||||
} else {
|
} else {
|
||||||
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
||||||
@ -3883,12 +3895,10 @@ getDFSRetry:
|
|||||||
pSMB->hdr.Mid = GetNextMid(ses->server);
|
pSMB->hdr.Mid = GetNextMid(ses->server);
|
||||||
pSMB->hdr.Tid = ses->ipc_tid;
|
pSMB->hdr.Tid = ses->ipc_tid;
|
||||||
pSMB->hdr.Uid = ses->Suid;
|
pSMB->hdr.Uid = ses->Suid;
|
||||||
if (ses->capabilities & CAP_STATUS32) {
|
if (ses->capabilities & CAP_STATUS32)
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
|
pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
|
||||||
}
|
if (ses->capabilities & CAP_DFS)
|
||||||
if (ses->capabilities & CAP_DFS) {
|
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_DFS;
|
pSMB->hdr.Flags2 |= SMBFLG2_DFS;
|
||||||
}
|
|
||||||
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
||||||
@ -4060,10 +4070,6 @@ oldQFSInfoRetry:
|
|||||||
(void **) &pSMBr);
|
(void **) &pSMBr);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
|
|
||||||
(void **) &pSMBr);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
params = 2; /* level */
|
params = 2; /* level */
|
||||||
pSMB->TotalDataCount = 0;
|
pSMB->TotalDataCount = 0;
|
||||||
@ -4265,7 +4271,7 @@ QFSAttributeRetry:
|
|||||||
*) (((char *) &pSMBr->hdr.Protocol) +
|
*) (((char *) &pSMBr->hdr.Protocol) +
|
||||||
data_offset);
|
data_offset);
|
||||||
memcpy(&tcon->fsAttrInfo, response_data,
|
memcpy(&tcon->fsAttrInfo, response_data,
|
||||||
sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
|
sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cifs_buf_release(pSMB);
|
cifs_buf_release(pSMB);
|
||||||
@ -4334,7 +4340,7 @@ QFSDeviceRetry:
|
|||||||
(((char *) &pSMBr->hdr.Protocol) +
|
(((char *) &pSMBr->hdr.Protocol) +
|
||||||
data_offset);
|
data_offset);
|
||||||
memcpy(&tcon->fsDevInfo, response_data,
|
memcpy(&tcon->fsDevInfo, response_data,
|
||||||
sizeof (FILE_SYSTEM_DEVICE_INFO));
|
sizeof(FILE_SYSTEM_DEVICE_INFO));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cifs_buf_release(pSMB);
|
cifs_buf_release(pSMB);
|
||||||
@ -4402,7 +4408,7 @@ QFSUnixRetry:
|
|||||||
*) (((char *) &pSMBr->hdr.Protocol) +
|
*) (((char *) &pSMBr->hdr.Protocol) +
|
||||||
data_offset);
|
data_offset);
|
||||||
memcpy(&tcon->fsUnixInfo, response_data,
|
memcpy(&tcon->fsUnixInfo, response_data,
|
||||||
sizeof (FILE_SYSTEM_UNIX_INFO));
|
sizeof(FILE_SYSTEM_UNIX_INFO));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cifs_buf_release(pSMB);
|
cifs_buf_release(pSMB);
|
||||||
@ -4612,7 +4618,7 @@ SetEOFRetry:
|
|||||||
strncpy(pSMB->FileName, fileName, name_len);
|
strncpy(pSMB->FileName, fileName, name_len);
|
||||||
}
|
}
|
||||||
params = 6 + name_len;
|
params = 6 + name_len;
|
||||||
data_count = sizeof (struct file_end_of_file_info);
|
data_count = sizeof(struct file_end_of_file_info);
|
||||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||||
pSMB->MaxDataCount = cpu_to_le16(4100);
|
pSMB->MaxDataCount = cpu_to_le16(4100);
|
||||||
pSMB->MaxSetupCount = 0;
|
pSMB->MaxSetupCount = 0;
|
||||||
@ -4800,7 +4806,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
|
|||||||
|
|
||||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
||||||
|
|
||||||
count = sizeof (FILE_BASIC_INFO);
|
count = sizeof(FILE_BASIC_INFO);
|
||||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
|
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
|
||||||
pSMB->SetupCount = 1;
|
pSMB->SetupCount = 1;
|
||||||
@ -4871,7 +4877,7 @@ SetTimesRetry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
params = 6 + name_len;
|
params = 6 + name_len;
|
||||||
count = sizeof (FILE_BASIC_INFO);
|
count = sizeof(FILE_BASIC_INFO);
|
||||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
|
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
|
||||||
pSMB->MaxSetupCount = 0;
|
pSMB->MaxSetupCount = 0;
|
||||||
@ -4900,7 +4906,7 @@ SetTimesRetry:
|
|||||||
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
|
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
|
||||||
pSMB->Reserved4 = 0;
|
pSMB->Reserved4 = 0;
|
||||||
pSMB->hdr.smb_buf_length += byte_count;
|
pSMB->hdr.smb_buf_length += byte_count;
|
||||||
memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
|
memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
|
||||||
pSMB->ByteCount = cpu_to_le16(byte_count);
|
pSMB->ByteCount = cpu_to_le16(byte_count);
|
||||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||||
@ -5003,7 +5009,7 @@ setPermsRetry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
params = 6 + name_len;
|
params = 6 + name_len;
|
||||||
count = sizeof (FILE_UNIX_BASIC_INFO);
|
count = sizeof(FILE_UNIX_BASIC_INFO);
|
||||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
|
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
|
||||||
pSMB->MaxSetupCount = 0;
|
pSMB->MaxSetupCount = 0;
|
||||||
|
@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
|||||||
struct mid_q_entry *mid_entry;
|
struct mid_q_entry *mid_entry;
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
if ( kthread_should_stop() ) {
|
if (kthread_should_stop()) {
|
||||||
/* the demux thread will exit normally
|
/* the demux thread will exit normally
|
||||||
next time through the loop */
|
next time through the loop */
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
|||||||
}
|
}
|
||||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
list_for_each(tmp, &GlobalTreeConnectionList) {
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
||||||
if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
|
if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
|
||||||
tcon->tidStatus = CifsNeedReconnect;
|
tcon->tidStatus = CifsNeedReconnect;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
/* do not want to be sending data on a socket we are freeing */
|
/* do not want to be sending data on a socket we are freeing */
|
||||||
@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
|||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
up(&server->tcpSem);
|
up(&server->tcpSem);
|
||||||
|
|
||||||
while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
|
while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
|
||||||
try_to_freeze();
|
try_to_freeze();
|
||||||
if (server->protocolType == IPV6) {
|
if (server->protocolType == IPV6) {
|
||||||
rc = ipv6_connect(&server->addr.sockAddr6,
|
rc = ipv6_connect(&server->addr.sockAddr6,
|
||||||
@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
|||||||
} else {
|
} else {
|
||||||
atomic_inc(&tcpSesReconnectCount);
|
atomic_inc(&tcpSesReconnectCount);
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
if ( !kthread_should_stop() )
|
if (!kthread_should_stop())
|
||||||
server->tcpStatus = CifsGood;
|
server->tcpStatus = CifsGood;
|
||||||
server->sequence_number = 0;
|
server->sequence_number = 0;
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
length = tcpSesAllocCount.counter;
|
length = tcpSesAllocCount.counter;
|
||||||
write_unlock(&GlobalSMBSeslock);
|
write_unlock(&GlobalSMBSeslock);
|
||||||
complete(&cifsd_complete);
|
complete(&cifsd_complete);
|
||||||
if (length > 1) {
|
if (length > 1)
|
||||||
mempool_resize(cifs_req_poolp,
|
mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
|
||||||
length + cifs_min_rcv,
|
GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_freezable();
|
set_freezable();
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
}
|
}
|
||||||
} else if (isLargeBuf) {
|
} else if (isLargeBuf) {
|
||||||
/* we are reusing a dirty large buf, clear its start */
|
/* we are reusing a dirty large buf, clear its start */
|
||||||
memset(bigbuf, 0, sizeof (struct smb_hdr));
|
memset(bigbuf, 0, sizeof(struct smb_hdr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smallbuf == NULL) {
|
if (smallbuf == NULL) {
|
||||||
@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
}
|
}
|
||||||
/* beginning of smb buffer is cleared in our buf_get */
|
/* beginning of smb buffer is cleared in our buf_get */
|
||||||
} else /* if existing small buf clear beginning */
|
} else /* if existing small buf clear beginning */
|
||||||
memset(smallbuf, 0, sizeof (struct smb_hdr));
|
memset(smallbuf, 0, sizeof(struct smb_hdr));
|
||||||
|
|
||||||
isLargeBuf = FALSE;
|
isLargeBuf = FALSE;
|
||||||
isMultiRsp = FALSE;
|
isMultiRsp = FALSE;
|
||||||
@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
iov.iov_len = 4;
|
iov.iov_len = 4;
|
||||||
smb_msg.msg_control = NULL;
|
smb_msg.msg_control = NULL;
|
||||||
smb_msg.msg_controllen = 0;
|
smb_msg.msg_controllen = 0;
|
||||||
|
pdu_length = 4; /* enough to get RFC1001 header */
|
||||||
|
incomplete_rcv:
|
||||||
length =
|
length =
|
||||||
kernel_recvmsg(csocket, &smb_msg,
|
kernel_recvmsg(csocket, &smb_msg,
|
||||||
&iov, 1, 4, 0 /* BB see socket.h flags */);
|
&iov, 1, pdu_length, 0 /* BB other flags? */);
|
||||||
|
|
||||||
if ( kthread_should_stop() ) {
|
if (kthread_should_stop()) {
|
||||||
break;
|
break;
|
||||||
} else if (server->tcpStatus == CifsNeedReconnect) {
|
} else if (server->tcpStatus == CifsNeedReconnect) {
|
||||||
cFYI(1, ("Reconnect after server stopped responding"));
|
cFYI(1, ("Reconnect after server stopped responding"));
|
||||||
@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
msleep(1); /* minimum sleep to prevent looping
|
msleep(1); /* minimum sleep to prevent looping
|
||||||
allowing socket to clear and app threads to set
|
allowing socket to clear and app threads to set
|
||||||
tcpStatus CifsNeedReconnect if server hung */
|
tcpStatus CifsNeedReconnect if server hung */
|
||||||
continue;
|
if (pdu_length < 4)
|
||||||
|
goto incomplete_rcv;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
} else if (length <= 0) {
|
} else if (length <= 0) {
|
||||||
if (server->tcpStatus == CifsNew) {
|
if (server->tcpStatus == CifsNew) {
|
||||||
cFYI(1, ("tcp session abend after SMBnegprot"));
|
cFYI(1, ("tcp session abend after SMBnegprot"));
|
||||||
@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
wake_up(&server->response_q);
|
wake_up(&server->response_q);
|
||||||
continue;
|
continue;
|
||||||
} else if (length < 4) {
|
} else if (length < 4) {
|
||||||
cFYI(1,
|
cFYI(1, ("less than four bytes received (%d bytes)",
|
||||||
("Frame under four bytes received (%d bytes long)",
|
|
||||||
length));
|
length));
|
||||||
cifs_reconnect(server);
|
pdu_length -= length;
|
||||||
csocket = server->ssocket;
|
msleep(1);
|
||||||
wake_up(&server->response_q);
|
goto incomplete_rcv;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The right amount was read from socket - 4 bytes */
|
/* The right amount was read from socket - 4 bytes */
|
||||||
@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
|
|
||||||
/* else we have an SMB response */
|
/* else we have an SMB response */
|
||||||
if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
|
if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
|
||||||
(pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
|
(pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
|
||||||
cERROR(1, ("Invalid size SMB length %d pdu_length %d",
|
cERROR(1, ("Invalid size SMB length %d pdu_length %d",
|
||||||
length, pdu_length+4));
|
length, pdu_length+4));
|
||||||
cifs_reconnect(server);
|
cifs_reconnect(server);
|
||||||
@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
total_read += length) {
|
total_read += length) {
|
||||||
length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
|
length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
|
||||||
pdu_length - total_read, 0);
|
pdu_length - total_read, 0);
|
||||||
if ( kthread_should_stop() ||
|
if (kthread_should_stop() ||
|
||||||
(length == -EINTR)) {
|
(length == -EINTR)) {
|
||||||
/* then will exit */
|
/* then will exit */
|
||||||
reconnect = 2;
|
reconnect = 2;
|
||||||
@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
|||||||
allowing socket to clear and app
|
allowing socket to clear and app
|
||||||
threads to set tcpStatus
|
threads to set tcpStatus
|
||||||
CifsNeedReconnect if server hung*/
|
CifsNeedReconnect if server hung*/
|
||||||
|
length = 0;
|
||||||
continue;
|
continue;
|
||||||
} else if (length <= 0) {
|
} else if (length <= 0) {
|
||||||
cERROR(1, ("Received no data, expecting %d",
|
cERROR(1, ("Received no data, expecting %d",
|
||||||
@ -631,9 +632,9 @@ multi_t2_fnd:
|
|||||||
/* Was previous buf put in mpx struct for multi-rsp? */
|
/* Was previous buf put in mpx struct for multi-rsp? */
|
||||||
if (!isMultiRsp) {
|
if (!isMultiRsp) {
|
||||||
/* smb buffer will be freed by user thread */
|
/* smb buffer will be freed by user thread */
|
||||||
if (isLargeBuf) {
|
if (isLargeBuf)
|
||||||
bigbuf = NULL;
|
bigbuf = NULL;
|
||||||
} else
|
else
|
||||||
smallbuf = NULL;
|
smallbuf = NULL;
|
||||||
}
|
}
|
||||||
wake_up_process(task_to_wake);
|
wake_up_process(task_to_wake);
|
||||||
@ -676,9 +677,8 @@ multi_t2_fnd:
|
|||||||
server->ssocket = NULL;
|
server->ssocket = NULL;
|
||||||
}
|
}
|
||||||
/* buffer usuallly freed in free_mid - need to free it here on exit */
|
/* buffer usuallly freed in free_mid - need to free it here on exit */
|
||||||
if (bigbuf != NULL)
|
cifs_buf_release(bigbuf);
|
||||||
cifs_buf_release(bigbuf);
|
if (smallbuf) /* no sense logging a debug message if NULL */
|
||||||
if (smallbuf != NULL)
|
|
||||||
cifs_small_buf_release(smallbuf);
|
cifs_small_buf_release(smallbuf);
|
||||||
|
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
@ -702,9 +702,8 @@ multi_t2_fnd:
|
|||||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
list_for_each(tmp, &GlobalSMBSessionList) {
|
||||||
ses = list_entry(tmp, struct cifsSesInfo,
|
ses = list_entry(tmp, struct cifsSesInfo,
|
||||||
cifsSessionList);
|
cifsSessionList);
|
||||||
if (ses->server == server) {
|
if (ses->server == server)
|
||||||
ses->status = CifsExiting;
|
ses->status = CifsExiting;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
@ -714,9 +713,8 @@ multi_t2_fnd:
|
|||||||
cFYI(1, ("Clearing Mid 0x%x - waking up ",
|
cFYI(1, ("Clearing Mid 0x%x - waking up ",
|
||||||
mid_entry->mid));
|
mid_entry->mid));
|
||||||
task_to_wake = mid_entry->tsk;
|
task_to_wake = mid_entry->tsk;
|
||||||
if (task_to_wake) {
|
if (task_to_wake)
|
||||||
wake_up_process(task_to_wake);
|
wake_up_process(task_to_wake);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
@ -749,18 +747,15 @@ multi_t2_fnd:
|
|||||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
list_for_each(tmp, &GlobalSMBSessionList) {
|
||||||
ses = list_entry(tmp, struct cifsSesInfo,
|
ses = list_entry(tmp, struct cifsSesInfo,
|
||||||
cifsSessionList);
|
cifsSessionList);
|
||||||
if (ses->server == server) {
|
if (ses->server == server)
|
||||||
ses->server = NULL;
|
ses->server = NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
write_unlock(&GlobalSMBSeslock);
|
write_unlock(&GlobalSMBSeslock);
|
||||||
|
|
||||||
kfree(server);
|
kfree(server);
|
||||||
if (length > 0) {
|
if (length > 0)
|
||||||
mempool_resize(cifs_req_poolp,
|
mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
|
||||||
length + cifs_min_rcv,
|
GFP_KERNEL);
|
||||||
GFP_KERNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1477,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
|||||||
if (psin_server->sin_port) { /* user overrode default port */
|
if (psin_server->sin_port) { /* user overrode default port */
|
||||||
rc = (*csocket)->ops->connect(*csocket,
|
rc = (*csocket)->ops->connect(*csocket,
|
||||||
(struct sockaddr *) psin_server,
|
(struct sockaddr *) psin_server,
|
||||||
sizeof (struct sockaddr_in), 0);
|
sizeof(struct sockaddr_in), 0);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
|||||||
|
|
||||||
rc = (*csocket)->ops->connect(*csocket,
|
rc = (*csocket)->ops->connect(*csocket,
|
||||||
(struct sockaddr *) psin_server,
|
(struct sockaddr *) psin_server,
|
||||||
sizeof (struct sockaddr_in), 0);
|
sizeof(struct sockaddr_in), 0);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
|||||||
psin_server->sin_port = htons(RFC1001_PORT);
|
psin_server->sin_port = htons(RFC1001_PORT);
|
||||||
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
||||||
psin_server,
|
psin_server,
|
||||||
sizeof (struct sockaddr_in), 0);
|
sizeof(struct sockaddr_in), 0);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
@ -1610,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
|
|||||||
if (psin_server->sin6_port) { /* user overrode default port */
|
if (psin_server->sin6_port) { /* user overrode default port */
|
||||||
rc = (*csocket)->ops->connect(*csocket,
|
rc = (*csocket)->ops->connect(*csocket,
|
||||||
(struct sockaddr *) psin_server,
|
(struct sockaddr *) psin_server,
|
||||||
sizeof (struct sockaddr_in6), 0);
|
sizeof(struct sockaddr_in6), 0);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
|
|||||||
|
|
||||||
rc = (*csocket)->ops->connect(*csocket,
|
rc = (*csocket)->ops->connect(*csocket,
|
||||||
(struct sockaddr *) psin_server,
|
(struct sockaddr *) psin_server,
|
||||||
sizeof (struct sockaddr_in6), 0);
|
sizeof(struct sockaddr_in6), 0);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
|
|||||||
if (!connected) {
|
if (!connected) {
|
||||||
psin_server->sin6_port = htons(RFC1001_PORT);
|
psin_server->sin6_port = htons(RFC1001_PORT);
|
||||||
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
||||||
psin_server, sizeof (struct sockaddr_in6), 0);
|
psin_server, sizeof(struct sockaddr_in6), 0);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
|||||||
cFYI(1, ("very large write cap"));
|
cFYI(1, ("very large write cap"));
|
||||||
#endif /* CIFS_DEBUG2 */
|
#endif /* CIFS_DEBUG2 */
|
||||||
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
|
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
|
||||||
cFYI(1, ("setting capabilities failed"));
|
if (vol_info == NULL) {
|
||||||
|
cFYI(1, ("resetting capabilities failed"));
|
||||||
|
} else
|
||||||
|
cERROR(1, ("Negotiating Unix capabilities "
|
||||||
|
"with the server failed. Consider "
|
||||||
|
"mounting with the Unix Extensions\n"
|
||||||
|
"disabled, if problems are found, "
|
||||||
|
"by specifying the nounix mount "
|
||||||
|
"option."));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1909,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
|
srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
|
||||||
if (srvTcp == NULL) {
|
if (!srvTcp) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
sock_release(csocket);
|
sock_release(csocket);
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
|
|
||||||
memcpy(&srvTcp->addr.sockAddr, &sin_server,
|
memcpy(&srvTcp->addr.sockAddr, &sin_server,
|
||||||
sizeof (struct sockaddr_in));
|
sizeof(struct sockaddr_in));
|
||||||
atomic_set(&srvTcp->inFlight, 0);
|
atomic_set(&srvTcp->inFlight, 0);
|
||||||
/* BB Add code for ipv6 case too */
|
/* BB Add code for ipv6 case too */
|
||||||
srvTcp->ssocket = csocket;
|
srvTcp->ssocket = csocket;
|
||||||
@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||||||
if (tsk)
|
if (tsk)
|
||||||
kthread_stop(tsk);
|
kthread_stop(tsk);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
cFYI(1, ("No session or bad tcon"));
|
cFYI(1, ("No session or bad tcon"));
|
||||||
|
if ((pSesInfo->server) &&
|
||||||
|
(pSesInfo->server->tsk)) {
|
||||||
|
struct task_struct *tsk;
|
||||||
|
force_sig(SIGKILL,
|
||||||
|
pSesInfo->server->tsk);
|
||||||
|
tsk = pSesInfo->server->tsk;
|
||||||
|
if (tsk)
|
||||||
|
kthread_stop(tsk);
|
||||||
|
}
|
||||||
|
}
|
||||||
sesInfoFree(pSesInfo);
|
sesInfoFree(pSesInfo);
|
||||||
/* pSesInfo = NULL; */
|
/* pSesInfo = NULL; */
|
||||||
}
|
}
|
||||||
@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
|||||||
tcon->ses = pSesInfo;
|
tcon->ses = pSesInfo;
|
||||||
|
|
||||||
/* do not care if following two calls succeed - informational */
|
/* do not care if following two calls succeed - informational */
|
||||||
CIFSSMBQFSDeviceInfo(xid, tcon);
|
if (!tcon->ipc) {
|
||||||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
CIFSSMBQFSDeviceInfo(xid, tcon);
|
||||||
|
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||||
|
}
|
||||||
|
|
||||||
/* tell server which Unix caps we support */
|
/* tell server which Unix caps we support */
|
||||||
if (tcon->ses->capabilities & CAP_UNIX)
|
if (tcon->ses->capabilities & CAP_UNIX)
|
||||||
@ -2526,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
sesssetup_nomem: /* do not return an error on nomem for the info strings,
|
sesssetup_nomem: /* do not return an error on nomem for the info strings,
|
||||||
since that could make reconnection harder, and
|
since that could make reconnection harder, and
|
||||||
reconnection might be needed to free memory */
|
reconnection might be needed to free memory */
|
||||||
if (smb_buffer)
|
cifs_buf_release(smb_buffer);
|
||||||
cifs_buf_release(smb_buffer);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|||||||
int remaining_words = 0;
|
int remaining_words = 0;
|
||||||
int bytes_returned = 0;
|
int bytes_returned = 0;
|
||||||
int len;
|
int len;
|
||||||
int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
|
int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
|
||||||
PNEGOTIATE_MESSAGE SecurityBlob;
|
PNEGOTIATE_MESSAGE SecurityBlob;
|
||||||
PCHALLENGE_MESSAGE SecurityBlob2;
|
PCHALLENGE_MESSAGE SecurityBlob2;
|
||||||
__u32 negotiate_flags, capabilities;
|
__u32 negotiate_flags, capabilities;
|
||||||
@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smb_buffer)
|
cifs_buf_release(smb_buffer);
|
||||||
cifs_buf_release(smb_buffer);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
char *ntlm_session_key, int ntlmv2_flag,
|
char *ntlm_session_key, int ntlmv2_flag,
|
||||||
const struct nls_table *nls_codepage)
|
const struct nls_table *nls_codepage)
|
||||||
{
|
{
|
||||||
struct smb_hdr *smb_buffer;
|
struct smb_hdr *smb_buffer;
|
||||||
struct smb_hdr *smb_buffer_response;
|
struct smb_hdr *smb_buffer_response;
|
||||||
@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
int remaining_words = 0;
|
int remaining_words = 0;
|
||||||
int bytes_returned = 0;
|
int bytes_returned = 0;
|
||||||
int len;
|
int len;
|
||||||
int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
|
int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
|
||||||
PAUTHENTICATE_MESSAGE SecurityBlob;
|
PAUTHENTICATE_MESSAGE SecurityBlob;
|
||||||
__u32 negotiate_flags, capabilities;
|
__u32 negotiate_flags, capabilities;
|
||||||
__u16 count;
|
__u16 count;
|
||||||
@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
smb_buffer_response = smb_buffer;
|
smb_buffer_response = smb_buffer;
|
||||||
pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
|
pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
|
||||||
pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
|
pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
|
||||||
|
|
||||||
/* send SMBsessionSetup here */
|
/* send SMBsessionSetup here */
|
||||||
header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
|
header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
|
||||||
@ -2921,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||||
|
|
||||||
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
||||||
CAP_EXTENDED_SECURITY;
|
CAP_EXTENDED_SECURITY;
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
|
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
|
||||||
capabilities |= CAP_UNICODE;
|
capabilities |= CAP_UNICODE;
|
||||||
@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
}
|
}
|
||||||
pSMB->req.Capabilities = cpu_to_le32(capabilities);
|
pSMB->req.Capabilities = cpu_to_le32(capabilities);
|
||||||
|
|
||||||
bcc_ptr = (char *) &pSMB->req.SecurityBlob;
|
bcc_ptr = (char *)&pSMB->req.SecurityBlob;
|
||||||
SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
|
SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
|
||||||
strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
|
strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
|
||||||
SecurityBlob->MessageType = NtLmAuthenticate;
|
SecurityBlob->MessageType = NtLmAuthenticate;
|
||||||
bcc_ptr += SecurityBlobLength;
|
bcc_ptr += SecurityBlobLength;
|
||||||
negotiate_flags =
|
negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
|
||||||
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
|
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
|
||||||
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
|
0x80000000 | NTLMSSP_NEGOTIATE_128;
|
||||||
0x80000000 | NTLMSSP_NEGOTIATE_128;
|
|
||||||
if (sign_CIFS_PDUs)
|
if (sign_CIFS_PDUs)
|
||||||
negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
|
negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
|
||||||
if (ntlmv2_flag)
|
if (ntlmv2_flag)
|
||||||
@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
SecurityBlob->DomainName.Length = 0;
|
SecurityBlob->DomainName.Length = 0;
|
||||||
SecurityBlob->DomainName.MaximumLength = 0;
|
SecurityBlob->DomainName.MaximumLength = 0;
|
||||||
} else {
|
} else {
|
||||||
__u16 len =
|
__u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
|
||||||
cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
|
|
||||||
nls_codepage);
|
nls_codepage);
|
||||||
len *= 2;
|
ln *= 2;
|
||||||
SecurityBlob->DomainName.MaximumLength =
|
SecurityBlob->DomainName.MaximumLength =
|
||||||
cpu_to_le16(len);
|
cpu_to_le16(ln);
|
||||||
SecurityBlob->DomainName.Buffer =
|
SecurityBlob->DomainName.Buffer =
|
||||||
cpu_to_le32(SecurityBlobLength);
|
cpu_to_le32(SecurityBlobLength);
|
||||||
bcc_ptr += len;
|
bcc_ptr += ln;
|
||||||
SecurityBlobLength += len;
|
SecurityBlobLength += ln;
|
||||||
SecurityBlob->DomainName.Length =
|
SecurityBlob->DomainName.Length = cpu_to_le16(ln);
|
||||||
cpu_to_le16(len);
|
|
||||||
}
|
}
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
SecurityBlob->UserName.Buffer = 0;
|
SecurityBlob->UserName.Buffer = 0;
|
||||||
SecurityBlob->UserName.Length = 0;
|
SecurityBlob->UserName.Length = 0;
|
||||||
SecurityBlob->UserName.MaximumLength = 0;
|
SecurityBlob->UserName.MaximumLength = 0;
|
||||||
} else {
|
} else {
|
||||||
__u16 len =
|
__u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
|
||||||
cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
|
|
||||||
nls_codepage);
|
nls_codepage);
|
||||||
len *= 2;
|
ln *= 2;
|
||||||
SecurityBlob->UserName.MaximumLength =
|
SecurityBlob->UserName.MaximumLength =
|
||||||
cpu_to_le16(len);
|
cpu_to_le16(ln);
|
||||||
SecurityBlob->UserName.Buffer =
|
SecurityBlob->UserName.Buffer =
|
||||||
cpu_to_le32(SecurityBlobLength);
|
cpu_to_le32(SecurityBlobLength);
|
||||||
bcc_ptr += len;
|
bcc_ptr += ln;
|
||||||
SecurityBlobLength += len;
|
SecurityBlobLength += ln;
|
||||||
SecurityBlob->UserName.Length =
|
SecurityBlob->UserName.Length = cpu_to_le16(ln);
|
||||||
cpu_to_le16(len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SecurityBlob->WorkstationName.Length =
|
/* SecurityBlob->WorkstationName.Length =
|
||||||
@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
SecurityBlob->DomainName.Length = 0;
|
SecurityBlob->DomainName.Length = 0;
|
||||||
SecurityBlob->DomainName.MaximumLength = 0;
|
SecurityBlob->DomainName.MaximumLength = 0;
|
||||||
} else {
|
} else {
|
||||||
__u16 len;
|
__u16 ln;
|
||||||
negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
|
negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
|
||||||
strncpy(bcc_ptr, domain, 63);
|
strncpy(bcc_ptr, domain, 63);
|
||||||
len = strnlen(domain, 64);
|
ln = strnlen(domain, 64);
|
||||||
SecurityBlob->DomainName.MaximumLength =
|
SecurityBlob->DomainName.MaximumLength =
|
||||||
cpu_to_le16(len);
|
cpu_to_le16(ln);
|
||||||
SecurityBlob->DomainName.Buffer =
|
SecurityBlob->DomainName.Buffer =
|
||||||
cpu_to_le32(SecurityBlobLength);
|
cpu_to_le32(SecurityBlobLength);
|
||||||
bcc_ptr += len;
|
bcc_ptr += ln;
|
||||||
SecurityBlobLength += len;
|
SecurityBlobLength += ln;
|
||||||
SecurityBlob->DomainName.Length = cpu_to_le16(len);
|
SecurityBlob->DomainName.Length = cpu_to_le16(ln);
|
||||||
}
|
}
|
||||||
if (user == NULL) {
|
if (user == NULL) {
|
||||||
SecurityBlob->UserName.Buffer = 0;
|
SecurityBlob->UserName.Buffer = 0;
|
||||||
SecurityBlob->UserName.Length = 0;
|
SecurityBlob->UserName.Length = 0;
|
||||||
SecurityBlob->UserName.MaximumLength = 0;
|
SecurityBlob->UserName.MaximumLength = 0;
|
||||||
} else {
|
} else {
|
||||||
__u16 len;
|
__u16 ln;
|
||||||
strncpy(bcc_ptr, user, 63);
|
strncpy(bcc_ptr, user, 63);
|
||||||
len = strnlen(user, 64);
|
ln = strnlen(user, 64);
|
||||||
SecurityBlob->UserName.MaximumLength =
|
SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
|
||||||
cpu_to_le16(len);
|
|
||||||
SecurityBlob->UserName.Buffer =
|
SecurityBlob->UserName.Buffer =
|
||||||
cpu_to_le32(SecurityBlobLength);
|
cpu_to_le32(SecurityBlobLength);
|
||||||
bcc_ptr += len;
|
bcc_ptr += ln;
|
||||||
SecurityBlobLength += len;
|
SecurityBlobLength += ln;
|
||||||
SecurityBlob->UserName.Length = cpu_to_le16(len);
|
SecurityBlob->UserName.Length = cpu_to_le16(ln);
|
||||||
}
|
}
|
||||||
/* BB fill in our workstation name if known BB */
|
/* BB fill in our workstation name if known BB */
|
||||||
|
|
||||||
@ -3100,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
|
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
|
||||||
&bytes_returned, 1);
|
&bytes_returned, 1);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
|
/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
|
||||||
} else if ((smb_buffer_response->WordCount == 3)
|
} else if ((smb_buffer_response->WordCount == 3) ||
|
||||||
|| (smb_buffer_response->WordCount == 4)) {
|
(smb_buffer_response->WordCount == 4)) {
|
||||||
__u16 action = le16_to_cpu(pSMBr->resp.Action);
|
__u16 action = le16_to_cpu(pSMBr->resp.Action);
|
||||||
__u16 blob_len =
|
__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
||||||
le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
|
||||||
if (action & GUEST_LOGIN)
|
if (action & GUEST_LOGIN)
|
||||||
cFYI(1, (" Guest login")); /* BB Should we set anything
|
cFYI(1, (" Guest login")); /* BB Should we set anything
|
||||||
in SesInfo struct ? */
|
in SesInfo struct ? */
|
||||||
@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
} else {
|
} else {
|
||||||
remaining_words = BCC(smb_buffer_response) / 2;
|
remaining_words = BCC(smb_buffer_response) / 2;
|
||||||
}
|
}
|
||||||
len =
|
len = UniStrnlen((wchar_t *) bcc_ptr,
|
||||||
UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
|
remaining_words - 1);
|
||||||
/* We look for obvious messed up bcc or strings in response so we do not go off
|
/* We look for obvious messed up bcc or strings in response so we do not go off
|
||||||
the end since (at least) WIN2K and Windows XP have a major bug in not null
|
the end since (at least) WIN2K and Windows XP have a major bug in not null
|
||||||
terminating last Unicode string in response */
|
terminating last Unicode string in response */
|
||||||
@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
<= BCC(smb_buffer_response)) {
|
<= BCC(smb_buffer_response)) {
|
||||||
if (ses->serverOS)
|
if (ses->serverOS)
|
||||||
kfree(ses->serverOS);
|
kfree(ses->serverOS);
|
||||||
ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
|
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
|
||||||
strncpy(ses->serverOS,bcc_ptr, len);
|
strncpy(ses->serverOS,bcc_ptr, len);
|
||||||
|
|
||||||
bcc_ptr += len;
|
bcc_ptr += len;
|
||||||
@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
bcc_ptr[0] = 0;
|
bcc_ptr[0] = 0;
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
} else
|
} else
|
||||||
cFYI(1,
|
cFYI(1, ("field of length %d "
|
||||||
("field of length %d "
|
|
||||||
"extends beyond end of smb ",
|
"extends beyond end of smb ",
|
||||||
len));
|
len));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,
|
cERROR(1, ("Security Blob extends beyond end "
|
||||||
(" Security Blob extends beyond end "
|
|
||||||
"of SMB"));
|
"of SMB"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1, ("No session structure passed in."));
|
cERROR(1, ("No session structure passed in."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,
|
cERROR(1, ("Invalid Word count %d: ",
|
||||||
(" Invalid Word count %d: ",
|
|
||||||
smb_buffer_response->WordCount));
|
smb_buffer_response->WordCount));
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smb_buffer)
|
cifs_buf_release(smb_buffer);
|
||||||
cifs_buf_release(smb_buffer);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
bcc_ptr = pByteArea(smb_buffer_response);
|
bcc_ptr = pByteArea(smb_buffer_response);
|
||||||
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
|
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
|
||||||
/* skip service field (NB: this field is always ASCII) */
|
/* skip service field (NB: this field is always ASCII) */
|
||||||
|
if (length == 3) {
|
||||||
|
if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
|
||||||
|
(bcc_ptr[2] == 'C')) {
|
||||||
|
cFYI(1, ("IPC connection"));
|
||||||
|
tcon->ipc = 1;
|
||||||
|
}
|
||||||
|
} else if (length == 2) {
|
||||||
|
if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
|
||||||
|
/* the most common case */
|
||||||
|
cFYI(1, ("disk share connection"));
|
||||||
|
}
|
||||||
|
}
|
||||||
bcc_ptr += length + 1;
|
bcc_ptr += length + 1;
|
||||||
strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
|
strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
|
||||||
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
|
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
|
||||||
@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
kfree(tcon->nativeFileSystem);
|
kfree(tcon->nativeFileSystem);
|
||||||
tcon->nativeFileSystem =
|
tcon->nativeFileSystem =
|
||||||
kzalloc(length + 2, GFP_KERNEL);
|
kzalloc(length + 2, GFP_KERNEL);
|
||||||
cifs_strfromUCS_le(tcon->nativeFileSystem,
|
if (tcon->nativeFileSystem)
|
||||||
(__le16 *) bcc_ptr,
|
cifs_strfromUCS_le(
|
||||||
length, nls_codepage);
|
tcon->nativeFileSystem,
|
||||||
|
(__le16 *) bcc_ptr,
|
||||||
|
length, nls_codepage);
|
||||||
bcc_ptr += 2 * length;
|
bcc_ptr += 2 * length;
|
||||||
bcc_ptr[0] = 0; /* null terminate the string */
|
bcc_ptr[0] = 0; /* null terminate the string */
|
||||||
bcc_ptr[1] = 0;
|
bcc_ptr[1] = 0;
|
||||||
@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
kfree(tcon->nativeFileSystem);
|
kfree(tcon->nativeFileSystem);
|
||||||
tcon->nativeFileSystem =
|
tcon->nativeFileSystem =
|
||||||
kzalloc(length + 1, GFP_KERNEL);
|
kzalloc(length + 1, GFP_KERNEL);
|
||||||
strncpy(tcon->nativeFileSystem, bcc_ptr,
|
if (tcon->nativeFileSystem)
|
||||||
length);
|
strncpy(tcon->nativeFileSystem, bcc_ptr,
|
||||||
|
length);
|
||||||
}
|
}
|
||||||
/* else do not bother copying these information fields*/
|
/* else do not bother copying these information fields*/
|
||||||
}
|
}
|
||||||
@ -3433,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
ses->ipc_tid = smb_buffer_response->Tid;
|
ses->ipc_tid = smb_buffer_response->Tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smb_buffer)
|
cifs_buf_release(smb_buffer);
|
||||||
cifs_buf_release(smb_buffer);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* vfs operations that deal with dentries
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* 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);
|
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||||
} else if (newinode) {
|
} else if (newinode) {
|
||||||
pCifsFile =
|
pCifsFile =
|
||||||
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
|
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
||||||
|
|
||||||
if (pCifsFile == NULL)
|
if (pCifsFile == NULL)
|
||||||
goto cifs_create_out;
|
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
|
/* BB Do not bother to decode buf since no
|
||||||
local inode yet to put timestamps in,
|
local inode yet to put timestamps in,
|
||||||
but we can reuse it safely */
|
but we can reuse it safely */
|
||||||
int bytes_written;
|
unsigned int bytes_written;
|
||||||
struct win_dev *pdev;
|
struct win_dev *pdev;
|
||||||
pdev = (struct win_dev *)buf;
|
pdev = (struct win_dev *)buf;
|
||||||
if (S_ISCHR(mode)) {
|
if (S_ISCHR(mode)) {
|
||||||
@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
|||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
cFYI(1,
|
cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p",
|
||||||
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
|
|
||||||
parent_dir_inode, direntry->d_name.name, direntry));
|
parent_dir_inode, direntry->d_name.name, direntry));
|
||||||
|
|
||||||
/* check whether path exists */
|
/* check whether path exists */
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
#include "cifsglob.h"
|
#include "cifsglob.h"
|
||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
|
#include "cifsfs.h"
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
||||||
|
@ -467,7 +467,7 @@ reopen_error_exit:
|
|||||||
int cifs_close(struct inode *inode, struct file *file)
|
int cifs_close(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int xid;
|
int xid, timeout;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct cifsFileInfo *pSMBFile =
|
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
|
/* no sense reconnecting to close a file that is
|
||||||
already closed */
|
already closed */
|
||||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
if (pTcon->tidStatus != CifsNeedReconnect) {
|
||||||
int timeout = 2;
|
timeout = 2;
|
||||||
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||||
&& (timeout < 1000) ) {
|
&& (timeout <= 2048)) {
|
||||||
/* Give write a better chance to get to
|
/* Give write a better chance to get to
|
||||||
server ahead of the close. We do not
|
server ahead of the close. We do not
|
||||||
want to add a wait_q here as it would
|
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->flist);
|
||||||
list_del(&pSMBFile->tlist);
|
list_del(&pSMBFile->tlist);
|
||||||
write_unlock(&GlobalSMBSeslock);
|
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(pSMBFile->search_resume_name);
|
||||||
kfree(file->private_data);
|
kfree(file->private_data);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
} else
|
} else
|
||||||
rc = -EBADF;
|
rc = -EBADF;
|
||||||
|
|
||||||
|
read_lock(&GlobalSMBSeslock);
|
||||||
if (list_empty(&(CIFS_I(inode)->openFileList))) {
|
if (list_empty(&(CIFS_I(inode)->openFileList))) {
|
||||||
cFYI(1, ("closing last open instance for inode %p", inode));
|
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
|
/* 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)->clientCanCacheRead = FALSE;
|
||||||
CIFS_I(inode)->clientCanCacheAll = FALSE;
|
CIFS_I(inode)->clientCanCacheAll = FALSE;
|
||||||
}
|
}
|
||||||
|
read_unlock(&GlobalSMBSeslock);
|
||||||
if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
|
if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
|
||||||
rc = CIFS_I(inode)->write_behind_rc;
|
rc = CIFS_I(inode)->write_behind_rc;
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
|||||||
mutex_lock(&fid->lock_mutex);
|
mutex_lock(&fid->lock_mutex);
|
||||||
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
||||||
if (pfLock->fl_start <= li->offset &&
|
if (pfLock->fl_start <= li->offset &&
|
||||||
length >= li->length) {
|
(pfLock->fl_start + length) >=
|
||||||
|
(li->offset + li->length)) {
|
||||||
stored_rc = CIFSSMBLock(xid, pTcon,
|
stored_rc = CIFSSMBLock(xid, pTcon,
|
||||||
netfid,
|
netfid,
|
||||||
li->length, li->offset,
|
li->length, li->offset,
|
||||||
@ -1022,6 +1042,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
|
refind_writable:
|
||||||
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
||||||
if (open_file->closePend)
|
if (open_file->closePend)
|
||||||
continue;
|
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_RDWR) ||
|
||||||
(open_file->pfile->f_flags & O_WRONLY))) {
|
(open_file->pfile->f_flags & O_WRONLY))) {
|
||||||
atomic_inc(&open_file->wrtPending);
|
atomic_inc(&open_file->wrtPending);
|
||||||
|
|
||||||
|
if (!open_file->invalidHandle) {
|
||||||
|
/* found a good writable file */
|
||||||
|
read_unlock(&GlobalSMBSeslock);
|
||||||
|
return open_file;
|
||||||
|
}
|
||||||
|
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
if ((open_file->invalidHandle) &&
|
/* Had to unlock since following call can block */
|
||||||
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
|
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
||||||
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
if (!rc) {
|
||||||
/* if it fails, try another handle - might be */
|
if (!open_file->closePend)
|
||||||
/* dangerous to hold up writepages with retry */
|
return open_file;
|
||||||
if (rc) {
|
else { /* start over in case this was deleted */
|
||||||
cFYI(1,
|
/* since the list could be modified */
|
||||||
("failed on reopen file in wp"));
|
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
/* can not use this handle, no write
|
atomic_dec(&open_file->wrtPending);
|
||||||
pending on this one after all */
|
goto refind_writable;
|
||||||
atomic_dec
|
|
||||||
(&open_file->wrtPending);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
@ -1709,7 +1755,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||||||
struct page *page;
|
struct page *page;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
int bytes_read = 0;
|
unsigned int bytes_read = 0;
|
||||||
unsigned int read_size, i;
|
unsigned int read_size, i;
|
||||||
char *smb_read_data = NULL;
|
char *smb_read_data = NULL;
|
||||||
struct smb_com_read_rsp *pSMBr;
|
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;
|
i += bytes_read >> PAGE_CACHE_SHIFT;
|
||||||
cifs_stats_bytes_read(pTcon, bytes_read);
|
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 */
|
i++; /* account for partial page */
|
||||||
|
|
||||||
/* server copy of file can have smaller size
|
/* 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);
|
inode->i_mode = le64_to_cpu(findData.Permissions);
|
||||||
/* since we set the inode type below we need to mask off
|
/* since we set the inode type below we need to mask off
|
||||||
to avoid strange results if bits set above */
|
to avoid strange results if bits set above */
|
||||||
inode->i_mode &= ~S_IFMT;
|
inode->i_mode &= ~S_IFMT;
|
||||||
if (type == UNIX_FILE) {
|
if (type == UNIX_FILE) {
|
||||||
inode->i_mode |= S_IFREG;
|
inode->i_mode |= S_IFREG;
|
||||||
} else if (type == UNIX_SYMLINK) {
|
} else if (type == UNIX_SYMLINK) {
|
||||||
@ -575,19 +575,33 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct inode_operations cifs_ipc_inode_ops = {
|
||||||
|
.lookup = cifs_lookup,
|
||||||
|
};
|
||||||
|
|
||||||
/* gets root inode */
|
/* gets root inode */
|
||||||
void cifs_read_inode(struct inode *inode)
|
void cifs_read_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
int xid;
|
int xid, rc;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(inode->i_sb);
|
cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
if (cifs_sb->tcon->unix_ext)
|
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
|
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 */
|
/* can not call macro FreeXid here since in a void func */
|
||||||
_FreeXid(xid);
|
_FreeXid(xid);
|
||||||
}
|
}
|
||||||
@ -919,18 +933,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||||||
goto mkdir_out;
|
goto mkdir_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mode &= ~current->fs->umask;
|
||||||
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
||||||
mode, NULL /* netfid */, pInfo, &oplock,
|
mode, NULL /* netfid */, pInfo, &oplock,
|
||||||
full_path, cifs_sb->local_nls,
|
full_path, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
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));
|
cFYI(1, ("posix mkdir returned 0x%x", rc));
|
||||||
d_drop(direntry);
|
d_drop(direntry);
|
||||||
} else {
|
} else {
|
||||||
int obj_type;
|
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;
|
goto mkdir_get_info;
|
||||||
|
}
|
||||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
|
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
|
||||||
to set uid/gid */
|
to set uid/gid */
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
@ -940,8 +961,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
|||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
|
|
||||||
newinode = new_inode(inode->i_sb);
|
newinode = new_inode(inode->i_sb);
|
||||||
if (newinode == NULL)
|
if (newinode == NULL) {
|
||||||
|
kfree(pInfo);
|
||||||
goto mkdir_get_info;
|
goto mkdir_get_info;
|
||||||
|
}
|
||||||
/* Is an i_ino of zero legal? */
|
/* Is an i_ino of zero legal? */
|
||||||
/* Are there sanity checks we can use to ensure that
|
/* Are there sanity checks we can use to ensure that
|
||||||
the server is really filling in that field? */
|
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);
|
kfree(pInfo);
|
||||||
goto mkdir_out;
|
goto mkdir_out;
|
||||||
}
|
}
|
||||||
|
mkdir_retry_old:
|
||||||
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
||||||
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
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);
|
i_size_write(inode, offset);
|
||||||
spin_unlock(&inode->i_lock);
|
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);
|
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||||
truncate_inode_pages(mapping, offset);
|
truncate_inode_pages(mapping, offset);
|
||||||
|
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||||
goto out_truncate;
|
goto out_truncate;
|
||||||
|
|
||||||
do_expand:
|
do_expand:
|
||||||
@ -1469,7 +1501,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||||||
atomic_dec(&open_file->wrtPending);
|
atomic_dec(&open_file->wrtPending);
|
||||||
cFYI(1, ("SetFSize for attrs rc = %d", rc));
|
cFYI(1, ("SetFSize for attrs rc = %d", rc));
|
||||||
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||||
int bytes_written;
|
unsigned int bytes_written;
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, pTcon,
|
||||||
nfid, 0, attrs->ia_size,
|
nfid, 0, attrs->ia_size,
|
||||||
&bytes_written, NULL, NULL,
|
&bytes_written, NULL, NULL,
|
||||||
@ -1502,7 +1534,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
int bytes_written;
|
unsigned int bytes_written;
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, pTcon,
|
||||||
netfid, 0,
|
netfid, 0,
|
||||||
attrs->ia_size,
|
attrs->ia_size,
|
||||||
|
@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
|||||||
char *tmp_path = NULL;
|
char *tmp_path = NULL;
|
||||||
char *tmpbuffer;
|
char *tmpbuffer;
|
||||||
unsigned char *referrals = NULL;
|
unsigned char *referrals = NULL;
|
||||||
int num_referrals = 0;
|
unsigned int num_referrals = 0;
|
||||||
int len;
|
int len;
|
||||||
__u16 fid;
|
__u16 fid;
|
||||||
|
|
||||||
|
@ -169,7 +169,6 @@ cifs_buf_get(void)
|
|||||||
void
|
void
|
||||||
cifs_buf_release(void *buf_to_free)
|
cifs_buf_release(void *buf_to_free)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (buf_to_free == NULL) {
|
if (buf_to_free == NULL) {
|
||||||
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
|
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
|
||||||
return;
|
return;
|
||||||
|
@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
|
|||||||
{ERRusempx, -EIO},
|
{ERRusempx, -EIO},
|
||||||
{ERRusestd, -EIO},
|
{ERRusestd, -EIO},
|
||||||
{ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
|
{ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
|
||||||
{ERRaccountexpired, -EACCES},
|
{ERRnoSuchUser, -EACCES},
|
||||||
|
/* {ERRaccountexpired, -EACCES},
|
||||||
{ERRbadclient, -EACCES},
|
{ERRbadclient, -EACCES},
|
||||||
{ERRbadLogonTime, -EACCES},
|
{ERRbadLogonTime, -EACCES},
|
||||||
{ERRpasswordExpired, -EACCES},
|
{ERRpasswordExpired, -EACCES},*/
|
||||||
|
{ERRaccountexpired, -EKEYEXPIRED},
|
||||||
|
{ERRbadclient, -EACCES},
|
||||||
|
{ERRbadLogonTime, -EACCES},
|
||||||
|
{ERRpasswordExpired, -EKEYEXPIRED},
|
||||||
|
|
||||||
{ERRnosupport, -EINVAL},
|
{ERRnosupport, -EINVAL},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
@ -270,7 +276,7 @@ static const struct {
|
|||||||
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
|
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
|
||||||
during the session setup } */
|
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_GROUP_EXISTS}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
|
ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
|
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
|
||||||
@ -285,10 +291,10 @@ static const struct {
|
|||||||
ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
|
ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
|
||||||
ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
|
ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
|
ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
|
||||||
ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
|
ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
|
||||||
ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
|
ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
|
||||||
ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
|
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_NONE_MAPPED}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
|
ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
|
ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
|
||||||
@ -585,7 +591,7 @@ static const struct {
|
|||||||
ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
|
ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
|
ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
|
||||||
ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
|
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_POSSIBLE_DEADLOCK}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
|
ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
|
ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
|
||||||
@ -754,7 +760,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
map_smb_to_linux_error(struct smb_hdr *smb)
|
map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int rc = -EIO; /* if transport error smb error may not be set */
|
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
|
/* translate the newer STATUS codes to old style SMB errors
|
||||||
* and then to POSIX errors */
|
* and then to POSIX errors */
|
||||||
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
__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);
|
cifs_print_status(err);
|
||||||
ntstatus_to_dos(err, &smberrclass, &smberrcode);
|
ntstatus_to_dos(err, &smberrclass, &smberrcode);
|
||||||
} else {
|
} else {
|
||||||
@ -813,7 +821,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
|||||||
}
|
}
|
||||||
/* else ERRHRD class errors or junk - return EIO */
|
/* 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));
|
smberrcode, rc));
|
||||||
|
|
||||||
/* generic corrective action e.g. reconnect SMB session on
|
/* 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));
|
cERROR(1, ("illegal hours %d", st->Hours));
|
||||||
days = sd->Day;
|
days = sd->Day;
|
||||||
month = sd->Month;
|
month = sd->Month;
|
||||||
if ((days > 31) || (month > 12))
|
if ((days > 31) || (month > 12)) {
|
||||||
cERROR(1, ("illegal date, month %d day: %d", month, days));
|
cERROR(1, ("illegal date, month %d day: %d", month, days));
|
||||||
|
if (month > 12)
|
||||||
|
month = 12;
|
||||||
|
}
|
||||||
month -= 1;
|
month -= 1;
|
||||||
days += total_days_of_prev_months[month];
|
days += total_days_of_prev_months[month];
|
||||||
days += 3652; /* account for difference in days between 1980 and 1970 */
|
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,
|
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;
|
loff_t local_size;
|
||||||
struct timespec local_mtime;
|
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,
|
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;
|
loff_t local_size;
|
||||||
struct timespec local_mtime;
|
struct timespec local_mtime;
|
||||||
@ -826,7 +826,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct qstr qstring;
|
struct qstr qstring;
|
||||||
struct cifsFileInfo *pCifsF;
|
struct cifsFileInfo *pCifsF;
|
||||||
unsigned obj_type;
|
unsigned int obj_type;
|
||||||
ino_t inum;
|
ino_t inum;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct inode *tmp_inode;
|
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++) {
|
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
|
||||||
if (current_entry == NULL) {
|
if (current_entry == NULL) {
|
||||||
/* evaluate whether this case is an error */
|
/* 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));
|
num_to_fill, i));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
103
fs/cifs/sess.c
103
fs/cifs/sess.c
@ -67,14 +67,59 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
|||||||
pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
|
pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
|
||||||
capabilities |= CAP_DFS;
|
capabilities |= CAP_DFS;
|
||||||
}
|
}
|
||||||
if (ses->capabilities & CAP_UNIX) {
|
if (ses->capabilities & CAP_UNIX)
|
||||||
capabilities |= CAP_UNIX;
|
capabilities |= CAP_UNIX;
|
||||||
}
|
|
||||||
|
|
||||||
/* BB check whether to init vcnum BB */
|
/* BB check whether to init vcnum BB */
|
||||||
return capabilities;
|
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,
|
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
|
||||||
const struct nls_table *nls_cp)
|
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 * bytes_ret;
|
||||||
bcc_ptr += 2; /* account for null termination */
|
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 */
|
unicode_domain_string(&bcc_ptr, ses, nls_cp);
|
||||||
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
|
unicode_oslm_strings(&bcc_ptr, nls_cp);
|
||||||
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;
|
*pbcc_area = bcc_ptr;
|
||||||
}
|
}
|
||||||
@ -203,14 +225,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
|||||||
if (len >= words_left)
|
if (len >= words_left)
|
||||||
return rc;
|
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 */
|
/* UTF-8 string will not grow more than four times as big as UCS-16 */
|
||||||
ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
|
ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
|
||||||
if (ses->serverOS != NULL) {
|
if (ses->serverOS != NULL)
|
||||||
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
|
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
|
||||||
nls_cp);
|
|
||||||
}
|
|
||||||
data += 2 * (len + 1);
|
data += 2 * (len + 1);
|
||||||
words_left -= len + 1;
|
words_left -= len + 1;
|
||||||
|
|
||||||
@ -220,8 +239,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
|||||||
if (len >= words_left)
|
if (len >= words_left)
|
||||||
return rc;
|
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 */
|
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
|
||||||
if (ses->serverNOS != NULL) {
|
if (ses->serverNOS != NULL) {
|
||||||
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
|
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)
|
if (len > words_left)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (ses->serverDomain)
|
kfree(ses->serverDomain);
|
||||||
kfree(ses->serverDomain);
|
|
||||||
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
|
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
|
||||||
if (ses->serverDomain != NULL) {
|
if (ses->serverDomain != NULL) {
|
||||||
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
|
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)
|
if (len >= bleft)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (ses->serverOS)
|
kfree(ses->serverOS);
|
||||||
kfree(ses->serverOS);
|
|
||||||
|
|
||||||
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
|
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
|
||||||
if (ses->serverOS)
|
if (ses->serverOS)
|
||||||
@ -289,8 +305,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
|
|||||||
if (len >= bleft)
|
if (len >= bleft)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (ses->serverNOS)
|
kfree(ses->serverNOS);
|
||||||
kfree(ses->serverNOS);
|
|
||||||
|
|
||||||
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
|
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
|
||||||
if (ses->serverNOS)
|
if (ses->serverNOS)
|
||||||
@ -479,7 +494,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
|||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
if (iov[0].iov_len % 2) {
|
if (iov[0].iov_len % 2) {
|
||||||
*bcc_ptr = 0;
|
*bcc_ptr = 0;
|
||||||
} bcc_ptr++;
|
bcc_ptr++;
|
||||||
|
}
|
||||||
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||||
} else
|
} else
|
||||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
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_base = str_area;
|
||||||
iov[1].iov_len = count;
|
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 */
|
/* SMB request buf freed in SendReceive2 */
|
||||||
|
|
||||||
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
|
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
|
||||||
|
@ -173,9 +173,10 @@
|
|||||||
#define ERRusestd 251 /* temporarily unable to use either raw
|
#define ERRusestd 251 /* temporarily unable to use either raw
|
||||||
or mpx */
|
or mpx */
|
||||||
#define ERR_NOTIFY_ENUM_DIR 1024
|
#define ERR_NOTIFY_ENUM_DIR 1024
|
||||||
|
#define ERRnoSuchUser 2238 /* user account does not exist */
|
||||||
#define ERRaccountexpired 2239
|
#define ERRaccountexpired 2239
|
||||||
#define ERRbadclient 2240
|
#define ERRbadclient 2240 /* can not logon from this client */
|
||||||
#define ERRbadLogonTime 2241
|
#define ERRbadLogonTime 2241 /* logon hours do not allow this */
|
||||||
#define ERRpasswordExpired 2242
|
#define ERRpasswordExpired 2242
|
||||||
#define ERRnetlogonNotStarted 2455
|
#define ERRnetlogonNotStarted 2455
|
||||||
#define ERRnosupport 0xFFFF
|
#define ERRnosupport 0xFFFF
|
||||||
|
@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
|
|||||||
if (temp == NULL)
|
if (temp == NULL)
|
||||||
return temp;
|
return temp;
|
||||||
else {
|
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->mid = smb_buffer->Mid; /* always LE */
|
||||||
temp->pid = current->pid;
|
temp->pid = current->pid;
|
||||||
temp->command = smb_buffer->Command;
|
temp->command = smb_buffer->Command;
|
||||||
@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
|||||||
iov.iov_len = len;
|
iov.iov_len = len;
|
||||||
|
|
||||||
smb_msg.msg_name = sin;
|
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_control = NULL;
|
||||||
smb_msg.msg_controllen = 0;
|
smb_msg.msg_controllen = 0;
|
||||||
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
|
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 */
|
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
||||||
|
|
||||||
smb_msg.msg_name = sin;
|
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_control = NULL;
|
||||||
smb_msg.msg_controllen = 0;
|
smb_msg.msg_controllen = 0;
|
||||||
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
|
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 */
|
} /* else ok - we are setting up session */
|
||||||
}
|
}
|
||||||
*ppmidQ = AllocMidQEntry(in_buf, ses);
|
*ppmidQ = AllocMidQEntry(in_buf, ses);
|
||||||
if (*ppmidQ == NULL) {
|
if (*ppmidQ == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
|
|||||||
int
|
int
|
||||||
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
|
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
|
||||||
const int long_op)
|
const int long_op, const int logError)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int receive_len;
|
unsigned int receive_len;
|
||||||
@ -465,7 +464,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||||||
wake_up(&ses->server->request_q);
|
wake_up(&ses->server->request_q);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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 reconnect tid and uid here? */
|
||||||
/* BB special case Errbadpassword and pwdexpired here */
|
rc = map_smb_to_linux_error(midQ->resp_buf, logError);
|
||||||
rc = map_smb_to_linux_error(midQ->resp_buf);
|
|
||||||
|
|
||||||
/* convert ByteCount if necessary */
|
/* convert ByteCount if necessary */
|
||||||
if (receive_len >=
|
if (receive_len >= sizeof(struct smb_hdr) - 4
|
||||||
sizeof (struct smb_hdr) -
|
/* do not count RFC1001 header */ +
|
||||||
4 /* do not count RFC1001 header */ +
|
|
||||||
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
|
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
|
||||||
BCC(midQ->resp_buf) =
|
BCC(midQ->resp_buf) =
|
||||||
le16_to_cpu(BCC_LE(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;
|
*pbytes_returned = out_buf->smb_buf_length;
|
||||||
|
|
||||||
/* BB special case reconnect tid and uid here? */
|
/* 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 */
|
/* convert ByteCount if necessary */
|
||||||
if (receive_len >=
|
if (receive_len >= sizeof(struct smb_hdr) - 4
|
||||||
sizeof (struct smb_hdr) -
|
/* do not count RFC1001 header */ +
|
||||||
4 /* do not count RFC1001 header */ +
|
|
||||||
(2 * out_buf->WordCount) + 2 /* bcc */ )
|
(2 * out_buf->WordCount) + 2 /* bcc */ )
|
||||||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||||
} else {
|
} else {
|
||||||
@ -993,12 +988,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||||||
*pbytes_returned = out_buf->smb_buf_length;
|
*pbytes_returned = out_buf->smb_buf_length;
|
||||||
|
|
||||||
/* BB special case reconnect tid and uid here? */
|
/* 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 */
|
/* convert ByteCount if necessary */
|
||||||
if (receive_len >=
|
if (receive_len >= sizeof(struct smb_hdr) - 4
|
||||||
sizeof (struct smb_hdr) -
|
/* do not count RFC1001 header */ +
|
||||||
4 /* do not count RFC1001 header */ +
|
|
||||||
(2 * out_buf->WordCount) + 2 /* bcc */ )
|
(2 * out_buf->WordCount) + 2 /* bcc */ )
|
||||||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||||
} else {
|
} else {
|
||||||
|
@ -261,21 +261,26 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
|||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
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;
|
__u16 fid;
|
||||||
int oplock = FALSE;
|
int oplock = FALSE;
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
if (experimEnabled)
|
||||||
FILE_OPEN, GENERIC_READ, 0, &fid,
|
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
||||||
&oplock, NULL, cifs_sb->local_nls,
|
FILE_OPEN, GENERIC_READ, 0, &fid,
|
||||||
cifs_sb->mnt_cifs_flags &
|
&oplock, NULL, cifs_sb->local_nls,
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
/* else rc is EOPNOTSUPP from above */
|
||||||
|
|
||||||
if(rc == 0) {
|
if(rc == 0) {
|
||||||
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
|
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
|
||||||
ea_value, buf_size,
|
ea_value, buf_size,
|
||||||
ACL_TYPE_ACCESS);
|
ACL_TYPE_ACCESS);
|
||||||
CIFSSMBClose(xid, pTcon, fid);
|
CIFSSMBClose(xid, pTcon, fid);
|
||||||
}
|
}
|
||||||
} */ /* BB enable after fixing up return data */
|
}
|
||||||
|
#endif /* EXPERIMENTAL */
|
||||||
#else
|
#else
|
||||||
cFYI(1, ("query POSIX ACL not supported yet"));
|
cFYI(1, ("query POSIX ACL not supported yet"));
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user