forked from Minki/linux
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
|
||||
------------
|
||||
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
|
||||
@ -6,7 +22,10 @@ done with "serverino" mount option). Add support for POSIX Unlink
|
||||
Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix"
|
||||
mount option to allow disabling the CIFS Unix Extensions for just
|
||||
that mount. Fix hang on spinlock in find_writable_file (race when
|
||||
reopening file after session crash).
|
||||
reopening file after session crash). Byte range unlock request to
|
||||
windows server could unlock more bytes (on server copy of file)
|
||||
than intended if start of unlock request is well before start of
|
||||
a previous byte range lock that we issued.
|
||||
|
||||
Version 1.49
|
||||
------------
|
||||
|
@ -3,4 +3,4 @@
|
||||
#
|
||||
obj-$(CONFIG_CIFS) += cifs.o
|
||||
|
||||
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o
|
||||
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifsacl.o
|
||||
|
@ -385,10 +385,9 @@ asn1_oid_decode(struct asn1_ctx *ctx,
|
||||
unsigned long *optr;
|
||||
|
||||
size = eoc - ctx->pointer + 1;
|
||||
*oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
|
||||
if (*oid == NULL) {
|
||||
*oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
|
||||
if (*oid == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
optr = *oid;
|
||||
|
||||
@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||
return 0;
|
||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||
|| (tag != ASN1_SEQ)) {
|
||||
cFYI(1,
|
||||
("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
|
||||
cls, con, tag, end, *end));
|
||||
cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
|
||||
cls, con, tag, end, *end));
|
||||
}
|
||||
|
||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||
|
@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||
i++;
|
||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
||||
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
||||
length =
|
||||
sprintf(buf,
|
||||
"\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
|
||||
"Attributes: 0x%x\nPathComponentMax: %d Status: %d",
|
||||
i, tcon->treeName,
|
||||
atomic_read(&tcon->useCount),
|
||||
tcon->nativeFileSystem,
|
||||
length = sprintf(buf, "\n%d) %s Uses: %d ", i,
|
||||
tcon->treeName, atomic_read(&tcon->useCount));
|
||||
buf += length;
|
||||
if (tcon->nativeFileSystem) {
|
||||
length = sprintf(buf, "Type: %s ",
|
||||
tcon->nativeFileSystem);
|
||||
buf += length;
|
||||
}
|
||||
length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x"
|
||||
"\nPathComponentMax: %d Status: %d",
|
||||
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
|
||||
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
||||
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
||||
@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer,
|
||||
if (count < 3) {
|
||||
/* single char or single char followed by null */
|
||||
c = flags_string[0];
|
||||
if (c == '0' || c == 'n' || c == 'N')
|
||||
if (c == '0' || c == 'n' || c == 'N') {
|
||||
extended_security = CIFSSEC_DEF; /* default */
|
||||
else if (c == '1' || c == 'y' || c == 'Y')
|
||||
return count;
|
||||
} else if (c == '1' || c == 'y' || c == 'Y') {
|
||||
extended_security = CIFSSEC_MAX;
|
||||
return count;
|
||||
return count;
|
||||
} else if (!isdigit(c)) {
|
||||
cERROR(1, ("invalid flag %c", c));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* else we have a number */
|
||||
|
||||
|
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
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2005
|
||||
* Copyright (c) International Business Machines Corp., 2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
@ -22,17 +22,65 @@
|
||||
#ifndef _CIFSACL_H
|
||||
#define _CIFSACL_H
|
||||
|
||||
struct cifs_sid {
|
||||
__u8 revision; /* revision level */
|
||||
__u8 num_subauths;
|
||||
__u8 authority[6];
|
||||
__u32 sub_auth[4];
|
||||
/* next sub_auth if any ... */
|
||||
|
||||
#define NUM_AUTHS 6 /* number of authority fields */
|
||||
#define NUM_SUBAUTHS 5 /* number of sub authority fields */
|
||||
#define NUM_WK_SIDS 7 /* number of well known sids */
|
||||
#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
|
||||
|
||||
#define READ_BIT 0x4
|
||||
#define WRITE_BIT 0x2
|
||||
#define EXEC_BIT 0x1
|
||||
|
||||
#define UBITSHIFT 6
|
||||
#define GBITSHIFT 3
|
||||
|
||||
struct cifs_ntsd {
|
||||
__le16 revision; /* revision level */
|
||||
__le16 type;
|
||||
__le32 osidoffset;
|
||||
__le32 gsidoffset;
|
||||
__le32 sacloffset;
|
||||
__le32 dacloffset;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* everyone */
|
||||
/* extern const struct cifs_sid sid_everyone;*/
|
||||
/* group users */
|
||||
/* extern const struct cifs_sid sid_user;*/
|
||||
struct cifs_sid {
|
||||
__u8 revision; /* revision level */
|
||||
__u8 num_subauth;
|
||||
__u8 authority[6];
|
||||
__le32 sub_auth[5]; /* sub_auth[num_subauth] */ /* BB FIXME endianness BB */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cifs_acl {
|
||||
__le16 revision; /* revision level */
|
||||
__le16 size;
|
||||
__le32 num_aces;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cifs_ntace { /* first part of ACE which contains perms */
|
||||
__u8 type;
|
||||
__u8 flags;
|
||||
__le16 size;
|
||||
__le32 access_req;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cifs_ace { /* last part of ACE which includes user info */
|
||||
__u8 revision; /* revision level */
|
||||
__u8 num_subauth;
|
||||
__u8 authority[6];
|
||||
__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 */
|
||||
|
@ -345,7 +345,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||
user = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||
if (user == NULL)
|
||||
goto calc_exit_2;
|
||||
len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
|
||||
len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
|
||||
UniStrupr(user);
|
||||
hmac_md5_update((char *)user, 2*len, pctxt);
|
||||
|
||||
@ -356,7 +356,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
|
||||
if (domain == NULL)
|
||||
goto calc_exit_1;
|
||||
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
|
||||
len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
|
||||
nls_cp);
|
||||
/* the following line was removed since it didn't work well
|
||||
with lower cased domain name that passed as an option.
|
||||
Maybe converting the domain name earlier makes sense */
|
||||
|
@ -49,10 +49,6 @@
|
||||
static struct quotactl_ops cifs_quotactl_ops;
|
||||
#endif /* QUOTA */
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
extern struct export_operations cifs_export_ops;
|
||||
#endif /* EXPERIMENTAL */
|
||||
|
||||
int cifsFYI = 0;
|
||||
int cifsERROR = 1;
|
||||
int traceSMB = 0;
|
||||
@ -240,9 +236,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
|
||||
return 0;
|
||||
} else /* file mode might have been restricted at mount time
|
||||
else /* file mode might have been restricted at mount time
|
||||
on the client (above and beyond ACL on servers) for
|
||||
servers which do not support setting and viewing mode bits,
|
||||
so allowing client to check permissions is useful */
|
||||
@ -312,15 +308,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
|
||||
seq_printf(s, ",domain=%s",
|
||||
cifs_sb->tcon->ses->domainName);
|
||||
}
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
|
||||
!(cifs_sb->tcon->unix_ext))
|
||||
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
|
||||
!(cifs_sb->tcon->unix_ext))
|
||||
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
|
||||
}
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
seq_printf(s, ",posixpaths");
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
|
||||
!(cifs_sb->tcon->unix_ext))
|
||||
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
|
||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
|
||||
!(cifs_sb->tcon->unix_ext))
|
||||
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
|
||||
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
|
||||
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
||||
}
|
||||
@ -346,7 +342,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
|
||||
if (pTcon) {
|
||||
cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
|
||||
} else {
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
FreeXid(xid);
|
||||
@ -716,7 +712,7 @@ static int
|
||||
cifs_init_inodecache(void)
|
||||
{
|
||||
cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
|
||||
sizeof (struct cifsInodeInfo),
|
||||
sizeof(struct cifsInodeInfo),
|
||||
0, (SLAB_RECLAIM_ACCOUNT|
|
||||
SLAB_MEM_SPREAD),
|
||||
cifs_init_once);
|
||||
@ -816,8 +812,8 @@ static int
|
||||
cifs_init_mids(void)
|
||||
{
|
||||
cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
|
||||
sizeof (struct mid_q_entry), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
sizeof(struct mid_q_entry), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (cifs_mid_cachep == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -829,8 +825,8 @@ cifs_init_mids(void)
|
||||
}
|
||||
|
||||
cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
|
||||
sizeof (struct oplock_q_entry), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
sizeof(struct oplock_q_entry), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (cifs_oplock_cachep == NULL) {
|
||||
mempool_destroy(cifs_mid_poolp);
|
||||
kmem_cache_destroy(cifs_mid_cachep);
|
||||
@ -882,7 +878,8 @@ static int cifs_oplock_thread(void *dummyarg)
|
||||
the call */
|
||||
/* mutex_lock(&inode->i_mutex);*/
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
rc = filemap_fdatawrite(inode->i_mapping);
|
||||
rc =
|
||||
filemap_fdatawrite(inode->i_mapping);
|
||||
if (CIFS_I(inode)->clientCanCacheRead
|
||||
== 0) {
|
||||
filemap_fdatawait(inode->i_mapping);
|
||||
@ -907,8 +904,7 @@ static int cifs_oplock_thread(void *dummyarg)
|
||||
0 /* len */ , 0 /* offset */, 0,
|
||||
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
||||
0 /* wait flag */);
|
||||
cFYI(1,
|
||||
("Oplock release rc = %d ", rc));
|
||||
cFYI(1, ("Oplock release rc = %d", rc));
|
||||
}
|
||||
} else
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* fs/cifs/cifsfs.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002, 2005
|
||||
* Copyright (c) International Business Machines Corp., 2002, 2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
@ -99,7 +99,12 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
|
||||
size_t, int);
|
||||
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
||||
extern int cifs_ioctl (struct inode *inode, struct file *filep,
|
||||
extern int cifs_ioctl(struct inode *inode, struct file *filep,
|
||||
unsigned int command, unsigned long arg);
|
||||
#define CIFS_VERSION "1.50"
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
extern struct export_operations cifs_export_ops;
|
||||
#endif /* EXPERIMENTAL */
|
||||
|
||||
#define CIFS_VERSION "1.51"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
#include "cifs_fs_sb.h"
|
||||
#include "cifsacl.h"
|
||||
/*
|
||||
* The sizes of various internal tables and strings
|
||||
*/
|
||||
@ -89,7 +90,8 @@ enum statusEnum {
|
||||
};
|
||||
|
||||
enum securityEnum {
|
||||
LANMAN = 0, /* Legacy LANMAN auth */
|
||||
PLAINTXT = 0, /* Legacy with Plaintext passwords */
|
||||
LANMAN, /* Legacy LANMAN auth */
|
||||
NTLM, /* Legacy NTLM012 auth with NTLM hash */
|
||||
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
|
||||
RawNTLMSSP, /* NTLMSSP without SPNEGO */
|
||||
@ -115,6 +117,17 @@ struct mac_key {
|
||||
} data;
|
||||
};
|
||||
|
||||
struct cifs_cred {
|
||||
int uid;
|
||||
int gid;
|
||||
int mode;
|
||||
int cecount;
|
||||
struct cifs_sid osid;
|
||||
struct cifs_sid gsid;
|
||||
struct cifs_ntace *ntaces;
|
||||
struct cifs_ace *aces;
|
||||
};
|
||||
|
||||
/*
|
||||
*****************************************************************
|
||||
* Except the CIFS PDUs themselves all the
|
||||
@ -279,6 +292,7 @@ struct cifsTconInfo {
|
||||
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
|
||||
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
|
||||
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
||||
unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */
|
||||
unsigned retry:1;
|
||||
unsigned nocase:1;
|
||||
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
|
||||
@ -329,6 +343,7 @@ struct cifsFileInfo {
|
||||
struct list_head llist; /* list of byte range locks we have. */
|
||||
unsigned closePend:1; /* file is marked to close */
|
||||
unsigned invalidHandle:1; /* file closed via session abend */
|
||||
unsigned messageMode:1; /* for pipes: message vs byte mode */
|
||||
atomic_t wrtPending; /* handle in use - defer close */
|
||||
struct semaphore fh_sem; /* prevents reopen race after dead ses*/
|
||||
char *search_resume_name; /* BB removeme BB */
|
||||
@ -464,6 +479,9 @@ struct dir_notify_req {
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
#define CIFSSEC_MAY_LANMAN 0x00010
|
||||
#define CIFSSEC_MAY_PLNTXT 0x00020
|
||||
#else
|
||||
#define CIFSSEC_MAY_LANMAN 0
|
||||
#define CIFSSEC_MAY_PLNTXT 0
|
||||
#endif /* weak passwords */
|
||||
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
|
||||
|
||||
@ -477,14 +495,23 @@ require use of the stronger protocol */
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
#define CIFSSEC_MUST_LANMAN 0x10010
|
||||
#define CIFSSEC_MUST_PLNTXT 0x20020
|
||||
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
|
||||
#ifdef CONFIG_CIFS_UPCALL
|
||||
#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
|
||||
#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 */
|
||||
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
|
||||
|
||||
#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
|
||||
#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
|
||||
#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
|
||||
/*
|
||||
*****************************************************************
|
||||
* All constants go here
|
||||
|
@ -215,6 +215,12 @@
|
||||
/* file_execute, file_read_attributes*/
|
||||
/* write_dac, and delete. */
|
||||
|
||||
#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
|
||||
#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
|
||||
| FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
|
||||
#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
|
||||
|
||||
|
||||
/*
|
||||
* Invalid readdir handle
|
||||
*/
|
||||
@ -360,10 +366,10 @@ struct smb_hdr {
|
||||
__u8 WordCount;
|
||||
} __attribute__((packed));
|
||||
/* given a pointer to an smb_hdr retrieve the value of byte count */
|
||||
#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
|
||||
#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
|
||||
#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
|
||||
#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
|
||||
/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
|
||||
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
|
||||
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
|
||||
|
||||
/*
|
||||
* Computer Name Length (since Netbios name was length 16 with last byte 0x20)
|
||||
@ -716,6 +722,14 @@ typedef struct smb_com_findclose_req {
|
||||
#define REQ_OPENDIRONLY 0x00000008
|
||||
#define REQ_EXTENDED_INFO 0x00000010
|
||||
|
||||
/* File type */
|
||||
#define DISK_TYPE 0x0000
|
||||
#define BYTE_PIPE_TYPE 0x0001
|
||||
#define MESSAGE_PIPE_TYPE 0x0002
|
||||
#define PRINTER_TYPE 0x0003
|
||||
#define COMM_DEV_TYPE 0x0004
|
||||
#define UNKNOWN_TYPE 0xFFFF
|
||||
|
||||
typedef struct smb_com_open_req { /* also handles create */
|
||||
struct smb_hdr hdr; /* wct = 24 */
|
||||
__u8 AndXCommand;
|
||||
|
@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
|
||||
int * /* bytes returned */ , const int long_op);
|
||||
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
|
||||
struct kvec *, int /* nvec to send */,
|
||||
int * /* type of buf returned */ , const int long_op);
|
||||
int * /* type of buf returned */ , const int long_op,
|
||||
const int logError /* whether to log status code*/ );
|
||||
extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
|
||||
struct cifsTconInfo *,
|
||||
struct smb_hdr * /* input */ ,
|
||||
@ -65,7 +66,7 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
||||
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
||||
enum securityEnum *secType);
|
||||
extern int cifs_inet_pton(int, char *source, void *dst);
|
||||
extern int map_smb_to_linux_error(struct smb_hdr *smb);
|
||||
extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
|
||||
extern void header_assemble(struct smb_hdr *, char /* command */ ,
|
||||
const struct cifsTconInfo *, int /* length of
|
||||
fixed section (word count) in two byte units */);
|
||||
@ -304,12 +305,13 @@ extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
|
||||
const char *pass);
|
||||
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
||||
const struct nls_table *);
|
||||
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
|
||||
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
|
||||
extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
|
||||
const struct nls_table *);
|
||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
|
||||
#endif /* CIFS_WEAK_PW_HASH */
|
||||
extern int parse_sec_desc(struct cifs_ntsd *, int);
|
||||
extern int CIFSSMBCopy(int xid,
|
||||
struct cifsTconInfo *source_tcon,
|
||||
const char *fromName,
|
||||
|
@ -34,10 +34,10 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include "cifspdu.h"
|
||||
#include "cifsglob.h"
|
||||
#include "cifsacl.h"
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_unicode.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifsacl.h"
|
||||
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
static struct {
|
||||
@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
|
||||
write_lock(&GlobalSMBSeslock);
|
||||
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
|
||||
open_file = list_entry(tmp, struct cifsFileInfo, tlist);
|
||||
if (open_file) {
|
||||
if (open_file)
|
||||
open_file->invalidHandle = TRUE;
|
||||
}
|
||||
}
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
/* 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.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
|
||||
|
||||
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
|
||||
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;
|
||||
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)(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;
|
||||
remain = seconds % MIN_TZ_ADJ;
|
||||
if (remain >= (MIN_TZ_ADJ / 2))
|
||||
@ -574,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||
server->secType = NTLM;
|
||||
else if (secFlags & CIFSSEC_MAY_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
|
||||
little endian */
|
||||
@ -604,22 +621,26 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||
if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
|
||||
(server->capabilities & CAP_EXTENDED_SECURITY)) {
|
||||
count = pSMBr->ByteCount;
|
||||
if (count < 16)
|
||||
if (count < 16) {
|
||||
rc = -EIO;
|
||||
else if (count == 16) {
|
||||
server->secType = RawNTLMSSP;
|
||||
if (server->socketUseCount.counter > 1) {
|
||||
if (memcmp(server->server_GUID,
|
||||
pSMBr->u.extended_response.
|
||||
GUID, 16) != 0) {
|
||||
cFYI(1, ("server UID changed"));
|
||||
memcpy(server->server_GUID,
|
||||
pSMBr->u.extended_response.GUID,
|
||||
16);
|
||||
}
|
||||
} else
|
||||
goto neg_err_exit;
|
||||
}
|
||||
|
||||
if (server->socketUseCount.counter > 1) {
|
||||
if (memcmp(server->server_GUID,
|
||||
pSMBr->u.extended_response.
|
||||
GUID, 16) != 0) {
|
||||
cFYI(1, ("server UID changed"));
|
||||
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 {
|
||||
rc = decode_negTokenInit(pSMBr->u.extended_response.
|
||||
SecurityBlob,
|
||||
@ -642,10 +663,12 @@ signing_check:
|
||||
/* MUST_SIGN already includes the MAY_SIGN FLAG
|
||||
so if this is zero it means that signing is disabled */
|
||||
cFYI(1, ("Signing disabled"));
|
||||
if (server->secMode & SECMODE_SIGN_REQUIRED)
|
||||
if (server->secMode & SECMODE_SIGN_REQUIRED) {
|
||||
cERROR(1, ("Server requires "
|
||||
"/proc/fs/cifs/PacketSigningEnabled "
|
||||
"to be on"));
|
||||
"packet signing to be enabled in "
|
||||
"/proc/fs/cifs/SecurityFlags."));
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
server->secMode &=
|
||||
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
|
||||
} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
|
||||
@ -1052,7 +1075,7 @@ PsxCreat:
|
||||
InformationLevel) - 4;
|
||||
offset = param_offset + params;
|
||||
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->PosixOpenFlags = cpu_to_le32(posix_flags);
|
||||
pdata->OpenFlags = cpu_to_le32(*pOplock);
|
||||
@ -1098,8 +1121,8 @@ PsxCreat:
|
||||
if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
|
||||
*pOplock |= CIFS_CREATE_ACTION;
|
||||
/* check to make sure response data is there */
|
||||
if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
|
||||
pRetData->Type = -1; /* unknown */
|
||||
if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
|
||||
pRetData->Type = cpu_to_le32(-1); /* unknown */
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
cFYI(1, ("unknown type"));
|
||||
#endif
|
||||
@ -1107,12 +1130,12 @@ PsxCreat:
|
||||
if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
|
||||
+ sizeof(FILE_UNIX_BASIC_INFO)) {
|
||||
cERROR(1, ("Open response data too small"));
|
||||
pRetData->Type = -1;
|
||||
pRetData->Type = cpu_to_le32(-1);
|
||||
goto psx_create_err;
|
||||
}
|
||||
memcpy((char *) pRetData,
|
||||
(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
|
||||
sizeof (FILE_UNIX_BASIC_INFO));
|
||||
sizeof(FILE_UNIX_BASIC_INFO));
|
||||
}
|
||||
|
||||
psx_create_err:
|
||||
@ -1193,9 +1216,9 @@ OldOpenRetry:
|
||||
}
|
||||
if (*pOplock & 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_MORE_INFO);
|
||||
/* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
|
||||
/* 0 = read
|
||||
@ -1310,9 +1333,8 @@ openRetry:
|
||||
}
|
||||
if (*pOplock & 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->DesiredAccess = cpu_to_le32(access_flags);
|
||||
pSMB->AllocationSize = 0;
|
||||
/* 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_len = pSMB->hdr.smb_buf_length + 4;
|
||||
rc = SendReceive2(xid, tcon->ses, iov,
|
||||
1 /* num iovecs */,
|
||||
&resp_buf_type, 0);
|
||||
rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
|
||||
&resp_buf_type, 0 /* not long op */, 1 /* log err */ );
|
||||
cifs_stats_inc(&tcon->num_reads);
|
||||
pSMBr = (READ_RSP *)iov[0].iov_base;
|
||||
if (rc) {
|
||||
@ -1446,11 +1467,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
|
||||
*nbytes = 0;
|
||||
} else {
|
||||
pReadData = (char *) (&pSMBr->hdr.Protocol) +
|
||||
le16_to_cpu(pSMBr->DataOffset);
|
||||
/* if (rc = copy_to_user(buf, pReadData, data_length)) {
|
||||
le16_to_cpu(pSMBr->DataOffset);
|
||||
/* if (rc = copy_to_user(buf, pReadData, data_length)) {
|
||||
cERROR(1,("Faulting on read rc = %d",rc));
|
||||
rc = -EFAULT;
|
||||
}*/ /* can not use copy_to_user when using page cache*/
|
||||
}*/ /* can not use copy_to_user when using page cache*/
|
||||
if (*buf)
|
||||
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,
|
||||
long_op);
|
||||
long_op, 0 /* do not log STATUS code */ );
|
||||
cifs_stats_inc(&tcon->num_writes);
|
||||
if (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"));
|
||||
return -EINVAL;
|
||||
} else if (data_count + *ppdata > end_of_smb) {
|
||||
cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
|
||||
cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
|
||||
*ppdata, data_count, (data_count + *ppdata),
|
||||
end_of_smb, pSMBr));
|
||||
return -EINVAL;
|
||||
@ -2615,7 +2636,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
reparse_buf->TargetNameOffset +
|
||||
reparse_buf->TargetNameLen) >
|
||||
end_of_smb) {
|
||||
cFYI(1,("reparse buf goes beyond SMB"));
|
||||
cFYI(1, ("reparse buf beyond SMB"));
|
||||
rc = -EIO;
|
||||
goto qreparse_out;
|
||||
}
|
||||
@ -3042,25 +3063,12 @@ GetExtAttrOut:
|
||||
|
||||
#endif /* CONFIG_POSIX */
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
/* Get Security Descriptor (by handle) from remote server for a file or dir */
|
||||
int
|
||||
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
||||
/* BB fix up return info */ char *acl_inf, const int buflen,
|
||||
const int acl_type /* ACCESS/DEFAULT not sure implication */)
|
||||
const int acl_type)
|
||||
{
|
||||
int rc = 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_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);
|
||||
if (rc) {
|
||||
cFYI(1, ("Send error in QuerySecDesc = %d", rc));
|
||||
} else { /* decode response */
|
||||
struct cifs_sid *psec_desc;
|
||||
struct cifs_ntsd *psec_desc;
|
||||
__le32 * parm;
|
||||
int parm_len;
|
||||
int data_len;
|
||||
@ -3105,8 +3114,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
||||
goto qsec_out;
|
||||
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
|
||||
|
||||
cERROR(1, ("smb %p parm %p data %p",
|
||||
pSMBr, parm, psec_desc)); /* BB removeme BB */
|
||||
cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
|
||||
|
||||
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
|
||||
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 */
|
||||
|
||||
acl_len = le32_to_cpu(*(__le32 *)parm);
|
||||
acl_len = le32_to_cpu(*parm);
|
||||
/* BB check if (acl_len > bufsize) */
|
||||
|
||||
parse_sec_desc(psec_desc, acl_len);
|
||||
@ -3128,6 +3136,7 @@ qsec_out:
|
||||
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
|
||||
return rc;
|
||||
}
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
|
||||
/* Legacy Query Path Information call for lookup to old servers such
|
||||
as Win9x/WinME */
|
||||
@ -3363,6 +3372,9 @@ UnixQPathInfoRetry:
|
||||
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
||||
|
||||
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 */
|
||||
} else {
|
||||
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
||||
@ -3883,12 +3895,10 @@ getDFSRetry:
|
||||
pSMB->hdr.Mid = GetNextMid(ses->server);
|
||||
pSMB->hdr.Tid = ses->ipc_tid;
|
||||
pSMB->hdr.Uid = ses->Suid;
|
||||
if (ses->capabilities & CAP_STATUS32) {
|
||||
if (ses->capabilities & CAP_STATUS32)
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
|
||||
}
|
||||
if (ses->capabilities & CAP_DFS) {
|
||||
if (ses->capabilities & CAP_DFS)
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_DFS;
|
||||
}
|
||||
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
||||
@ -4060,10 +4070,6 @@ oldQFSInfoRetry:
|
||||
(void **) &pSMBr);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
|
||||
(void **) &pSMBr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
params = 2; /* level */
|
||||
pSMB->TotalDataCount = 0;
|
||||
@ -4265,7 +4271,7 @@ QFSAttributeRetry:
|
||||
*) (((char *) &pSMBr->hdr.Protocol) +
|
||||
data_offset);
|
||||
memcpy(&tcon->fsAttrInfo, response_data,
|
||||
sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
|
||||
sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
|
||||
}
|
||||
}
|
||||
cifs_buf_release(pSMB);
|
||||
@ -4334,7 +4340,7 @@ QFSDeviceRetry:
|
||||
(((char *) &pSMBr->hdr.Protocol) +
|
||||
data_offset);
|
||||
memcpy(&tcon->fsDevInfo, response_data,
|
||||
sizeof (FILE_SYSTEM_DEVICE_INFO));
|
||||
sizeof(FILE_SYSTEM_DEVICE_INFO));
|
||||
}
|
||||
}
|
||||
cifs_buf_release(pSMB);
|
||||
@ -4402,7 +4408,7 @@ QFSUnixRetry:
|
||||
*) (((char *) &pSMBr->hdr.Protocol) +
|
||||
data_offset);
|
||||
memcpy(&tcon->fsUnixInfo, response_data,
|
||||
sizeof (FILE_SYSTEM_UNIX_INFO));
|
||||
sizeof(FILE_SYSTEM_UNIX_INFO));
|
||||
}
|
||||
}
|
||||
cifs_buf_release(pSMB);
|
||||
@ -4612,7 +4618,7 @@ SetEOFRetry:
|
||||
strncpy(pSMB->FileName, fileName, 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->MaxDataCount = cpu_to_le16(4100);
|
||||
pSMB->MaxSetupCount = 0;
|
||||
@ -4800,7 +4806,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
|
||||
|
||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
||||
|
||||
count = sizeof (FILE_BASIC_INFO);
|
||||
count = sizeof(FILE_BASIC_INFO);
|
||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
|
||||
pSMB->SetupCount = 1;
|
||||
@ -4871,7 +4877,7 @@ SetTimesRetry:
|
||||
}
|
||||
|
||||
params = 6 + name_len;
|
||||
count = sizeof (FILE_BASIC_INFO);
|
||||
count = sizeof(FILE_BASIC_INFO);
|
||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
|
||||
pSMB->MaxSetupCount = 0;
|
||||
@ -4900,7 +4906,7 @@ SetTimesRetry:
|
||||
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
|
||||
pSMB->Reserved4 = 0;
|
||||
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);
|
||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
@ -5003,7 +5009,7 @@ setPermsRetry:
|
||||
}
|
||||
|
||||
params = 6 + name_len;
|
||||
count = sizeof (FILE_UNIX_BASIC_INFO);
|
||||
count = sizeof(FILE_UNIX_BASIC_INFO);
|
||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
|
||||
pSMB->MaxSetupCount = 0;
|
||||
|
@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
struct mid_q_entry *mid_entry;
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if ( kthread_should_stop() ) {
|
||||
if (kthread_should_stop()) {
|
||||
/* the demux thread will exit normally
|
||||
next time through the loop */
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
}
|
||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
/* 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);
|
||||
up(&server->tcpSem);
|
||||
|
||||
while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
|
||||
while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
|
||||
try_to_freeze();
|
||||
if (server->protocolType == IPV6) {
|
||||
rc = ipv6_connect(&server->addr.sockAddr6,
|
||||
@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
} else {
|
||||
atomic_inc(&tcpSesReconnectCount);
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if ( !kthread_should_stop() )
|
||||
if (!kthread_should_stop())
|
||||
server->tcpStatus = CifsGood;
|
||||
server->sequence_number = 0;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
length = tcpSesAllocCount.counter;
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
complete(&cifsd_complete);
|
||||
if (length > 1) {
|
||||
mempool_resize(cifs_req_poolp,
|
||||
length + cifs_min_rcv,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
if (length > 1)
|
||||
mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
|
||||
GFP_KERNEL);
|
||||
|
||||
set_freezable();
|
||||
while (!kthread_should_stop()) {
|
||||
@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
}
|
||||
} else if (isLargeBuf) {
|
||||
/* 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) {
|
||||
@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
}
|
||||
/* beginning of smb buffer is cleared in our buf_get */
|
||||
} else /* if existing small buf clear beginning */
|
||||
memset(smallbuf, 0, sizeof (struct smb_hdr));
|
||||
memset(smallbuf, 0, sizeof(struct smb_hdr));
|
||||
|
||||
isLargeBuf = FALSE;
|
||||
isMultiRsp = FALSE;
|
||||
@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
iov.iov_len = 4;
|
||||
smb_msg.msg_control = NULL;
|
||||
smb_msg.msg_controllen = 0;
|
||||
pdu_length = 4; /* enough to get RFC1001 header */
|
||||
incomplete_rcv:
|
||||
length =
|
||||
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;
|
||||
} else if (server->tcpStatus == CifsNeedReconnect) {
|
||||
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
|
||||
allowing socket to clear and app threads to set
|
||||
tcpStatus CifsNeedReconnect if server hung */
|
||||
continue;
|
||||
if (pdu_length < 4)
|
||||
goto incomplete_rcv;
|
||||
else
|
||||
continue;
|
||||
} else if (length <= 0) {
|
||||
if (server->tcpStatus == CifsNew) {
|
||||
cFYI(1, ("tcp session abend after SMBnegprot"));
|
||||
@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
wake_up(&server->response_q);
|
||||
continue;
|
||||
} else if (length < 4) {
|
||||
cFYI(1,
|
||||
("Frame under four bytes received (%d bytes long)",
|
||||
cFYI(1, ("less than four bytes received (%d bytes)",
|
||||
length));
|
||||
cifs_reconnect(server);
|
||||
csocket = server->ssocket;
|
||||
wake_up(&server->response_q);
|
||||
continue;
|
||||
pdu_length -= length;
|
||||
msleep(1);
|
||||
goto incomplete_rcv;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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",
|
||||
length, pdu_length+4));
|
||||
cifs_reconnect(server);
|
||||
@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
total_read += length) {
|
||||
length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
|
||||
pdu_length - total_read, 0);
|
||||
if ( kthread_should_stop() ||
|
||||
if (kthread_should_stop() ||
|
||||
(length == -EINTR)) {
|
||||
/* then will exit */
|
||||
reconnect = 2;
|
||||
@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
allowing socket to clear and app
|
||||
threads to set tcpStatus
|
||||
CifsNeedReconnect if server hung*/
|
||||
length = 0;
|
||||
continue;
|
||||
} else if (length <= 0) {
|
||||
cERROR(1, ("Received no data, expecting %d",
|
||||
@ -631,9 +632,9 @@ multi_t2_fnd:
|
||||
/* Was previous buf put in mpx struct for multi-rsp? */
|
||||
if (!isMultiRsp) {
|
||||
/* smb buffer will be freed by user thread */
|
||||
if (isLargeBuf) {
|
||||
if (isLargeBuf)
|
||||
bigbuf = NULL;
|
||||
} else
|
||||
else
|
||||
smallbuf = NULL;
|
||||
}
|
||||
wake_up_process(task_to_wake);
|
||||
@ -676,9 +677,8 @@ multi_t2_fnd:
|
||||
server->ssocket = NULL;
|
||||
}
|
||||
/* buffer usuallly freed in free_mid - need to free it here on exit */
|
||||
if (bigbuf != NULL)
|
||||
cifs_buf_release(bigbuf);
|
||||
if (smallbuf != NULL)
|
||||
cifs_buf_release(bigbuf);
|
||||
if (smallbuf) /* no sense logging a debug message if NULL */
|
||||
cifs_small_buf_release(smallbuf);
|
||||
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
@ -702,9 +702,8 @@ multi_t2_fnd:
|
||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
||||
ses = list_entry(tmp, struct cifsSesInfo,
|
||||
cifsSessionList);
|
||||
if (ses->server == server) {
|
||||
if (ses->server == server)
|
||||
ses->status = CifsExiting;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
@ -714,9 +713,8 @@ multi_t2_fnd:
|
||||
cFYI(1, ("Clearing Mid 0x%x - waking up ",
|
||||
mid_entry->mid));
|
||||
task_to_wake = mid_entry->tsk;
|
||||
if (task_to_wake) {
|
||||
if (task_to_wake)
|
||||
wake_up_process(task_to_wake);
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
@ -749,18 +747,15 @@ multi_t2_fnd:
|
||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
||||
ses = list_entry(tmp, struct cifsSesInfo,
|
||||
cifsSessionList);
|
||||
if (ses->server == server) {
|
||||
if (ses->server == server)
|
||||
ses->server = NULL;
|
||||
}
|
||||
}
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
|
||||
kfree(server);
|
||||
if (length > 0) {
|
||||
mempool_resize(cifs_req_poolp,
|
||||
length + cifs_min_rcv,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
if (length > 0)
|
||||
mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
|
||||
GFP_KERNEL);
|
||||
|
||||
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 */
|
||||
rc = (*csocket)->ops->connect(*csocket,
|
||||
(struct sockaddr *) psin_server,
|
||||
sizeof (struct sockaddr_in), 0);
|
||||
sizeof(struct sockaddr_in), 0);
|
||||
if (rc >= 0)
|
||||
connected = 1;
|
||||
}
|
||||
@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
||||
|
||||
rc = (*csocket)->ops->connect(*csocket,
|
||||
(struct sockaddr *) psin_server,
|
||||
sizeof (struct sockaddr_in), 0);
|
||||
sizeof(struct sockaddr_in), 0);
|
||||
if (rc >= 0)
|
||||
connected = 1;
|
||||
}
|
||||
@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
||||
psin_server->sin_port = htons(RFC1001_PORT);
|
||||
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
||||
psin_server,
|
||||
sizeof (struct sockaddr_in), 0);
|
||||
sizeof(struct sockaddr_in), 0);
|
||||
if (rc >= 0)
|
||||
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 */
|
||||
rc = (*csocket)->ops->connect(*csocket,
|
||||
(struct sockaddr *) psin_server,
|
||||
sizeof (struct sockaddr_in6), 0);
|
||||
sizeof(struct sockaddr_in6), 0);
|
||||
if (rc >= 0)
|
||||
connected = 1;
|
||||
}
|
||||
@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
|
||||
|
||||
rc = (*csocket)->ops->connect(*csocket,
|
||||
(struct sockaddr *) psin_server,
|
||||
sizeof (struct sockaddr_in6), 0);
|
||||
sizeof(struct sockaddr_in6), 0);
|
||||
if (rc >= 0)
|
||||
connected = 1;
|
||||
}
|
||||
@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
|
||||
if (!connected) {
|
||||
psin_server->sin6_port = htons(RFC1001_PORT);
|
||||
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
||||
psin_server, sizeof (struct sockaddr_in6), 0);
|
||||
psin_server, sizeof(struct sockaddr_in6), 0);
|
||||
if (rc >= 0)
|
||||
connected = 1;
|
||||
}
|
||||
@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
||||
cFYI(1, ("very large write cap"));
|
||||
#endif /* CIFS_DEBUG2 */
|
||||
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;
|
||||
}
|
||||
|
||||
srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
|
||||
if (srvTcp == NULL) {
|
||||
srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
|
||||
if (!srvTcp) {
|
||||
rc = -ENOMEM;
|
||||
sock_release(csocket);
|
||||
kfree(volume_info.UNC);
|
||||
@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
FreeXid(xid);
|
||||
return rc;
|
||||
} else {
|
||||
memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
|
||||
memcpy(&srvTcp->addr.sockAddr, &sin_server,
|
||||
sizeof (struct sockaddr_in));
|
||||
sizeof(struct sockaddr_in));
|
||||
atomic_set(&srvTcp->inFlight, 0);
|
||||
/* BB Add code for ipv6 case too */
|
||||
srvTcp->ssocket = csocket;
|
||||
@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
if (tsk)
|
||||
kthread_stop(tsk);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
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);
|
||||
/* pSesInfo = NULL; */
|
||||
}
|
||||
@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||
tcon->ses = pSesInfo;
|
||||
|
||||
/* do not care if following two calls succeed - informational */
|
||||
CIFSSMBQFSDeviceInfo(xid, tcon);
|
||||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||
if (!tcon->ipc) {
|
||||
CIFSSMBQFSDeviceInfo(xid, tcon);
|
||||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||
}
|
||||
|
||||
/* tell server which Unix caps we support */
|
||||
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,
|
||||
since that could make reconnection harder, and
|
||||
reconnection might be needed to free memory */
|
||||
if (smb_buffer)
|
||||
cifs_buf_release(smb_buffer);
|
||||
cifs_buf_release(smb_buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||
int remaining_words = 0;
|
||||
int bytes_returned = 0;
|
||||
int len;
|
||||
int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
|
||||
int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
|
||||
PNEGOTIATE_MESSAGE SecurityBlob;
|
||||
PCHALLENGE_MESSAGE SecurityBlob2;
|
||||
__u32 negotiate_flags, capabilities;
|
||||
@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
if (smb_buffer)
|
||||
cifs_buf_release(smb_buffer);
|
||||
cifs_buf_release(smb_buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
static int
|
||||
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
char *ntlm_session_key, int ntlmv2_flag,
|
||||
const struct nls_table *nls_codepage)
|
||||
char *ntlm_session_key, int ntlmv2_flag,
|
||||
const struct nls_table *nls_codepage)
|
||||
{
|
||||
struct smb_hdr *smb_buffer;
|
||||
struct smb_hdr *smb_buffer_response;
|
||||
@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
int remaining_words = 0;
|
||||
int bytes_returned = 0;
|
||||
int len;
|
||||
int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
|
||||
int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
|
||||
PAUTHENTICATE_MESSAGE SecurityBlob;
|
||||
__u32 negotiate_flags, capabilities;
|
||||
__u16 count;
|
||||
@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
return -ENOMEM;
|
||||
}
|
||||
smb_buffer_response = smb_buffer;
|
||||
pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
|
||||
pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
|
||||
pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
|
||||
pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
|
||||
|
||||
/* send SMBsessionSetup here */
|
||||
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;
|
||||
|
||||
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
||||
CAP_EXTENDED_SECURITY;
|
||||
CAP_EXTENDED_SECURITY;
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
|
||||
capabilities |= CAP_UNICODE;
|
||||
@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
}
|
||||
pSMB->req.Capabilities = cpu_to_le32(capabilities);
|
||||
|
||||
bcc_ptr = (char *) &pSMB->req.SecurityBlob;
|
||||
SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
|
||||
bcc_ptr = (char *)&pSMB->req.SecurityBlob;
|
||||
SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
|
||||
strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
|
||||
SecurityBlob->MessageType = NtLmAuthenticate;
|
||||
bcc_ptr += SecurityBlobLength;
|
||||
negotiate_flags =
|
||||
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
|
||||
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
|
||||
0x80000000 | NTLMSSP_NEGOTIATE_128;
|
||||
negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
|
||||
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
|
||||
0x80000000 | NTLMSSP_NEGOTIATE_128;
|
||||
if (sign_CIFS_PDUs)
|
||||
negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
|
||||
if (ntlmv2_flag)
|
||||
@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
SecurityBlob->DomainName.Length = 0;
|
||||
SecurityBlob->DomainName.MaximumLength = 0;
|
||||
} else {
|
||||
__u16 len =
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
|
||||
__u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
|
||||
nls_codepage);
|
||||
len *= 2;
|
||||
ln *= 2;
|
||||
SecurityBlob->DomainName.MaximumLength =
|
||||
cpu_to_le16(len);
|
||||
cpu_to_le16(ln);
|
||||
SecurityBlob->DomainName.Buffer =
|
||||
cpu_to_le32(SecurityBlobLength);
|
||||
bcc_ptr += len;
|
||||
SecurityBlobLength += len;
|
||||
SecurityBlob->DomainName.Length =
|
||||
cpu_to_le16(len);
|
||||
bcc_ptr += ln;
|
||||
SecurityBlobLength += ln;
|
||||
SecurityBlob->DomainName.Length = cpu_to_le16(ln);
|
||||
}
|
||||
if (user == NULL) {
|
||||
SecurityBlob->UserName.Buffer = 0;
|
||||
SecurityBlob->UserName.Length = 0;
|
||||
SecurityBlob->UserName.MaximumLength = 0;
|
||||
} else {
|
||||
__u16 len =
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
|
||||
__u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
|
||||
nls_codepage);
|
||||
len *= 2;
|
||||
ln *= 2;
|
||||
SecurityBlob->UserName.MaximumLength =
|
||||
cpu_to_le16(len);
|
||||
cpu_to_le16(ln);
|
||||
SecurityBlob->UserName.Buffer =
|
||||
cpu_to_le32(SecurityBlobLength);
|
||||
bcc_ptr += len;
|
||||
SecurityBlobLength += len;
|
||||
SecurityBlob->UserName.Length =
|
||||
cpu_to_le16(len);
|
||||
bcc_ptr += ln;
|
||||
SecurityBlobLength += ln;
|
||||
SecurityBlob->UserName.Length = cpu_to_le16(ln);
|
||||
}
|
||||
|
||||
/* SecurityBlob->WorkstationName.Length =
|
||||
@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
SecurityBlob->DomainName.Length = 0;
|
||||
SecurityBlob->DomainName.MaximumLength = 0;
|
||||
} else {
|
||||
__u16 len;
|
||||
__u16 ln;
|
||||
negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
|
||||
strncpy(bcc_ptr, domain, 63);
|
||||
len = strnlen(domain, 64);
|
||||
ln = strnlen(domain, 64);
|
||||
SecurityBlob->DomainName.MaximumLength =
|
||||
cpu_to_le16(len);
|
||||
cpu_to_le16(ln);
|
||||
SecurityBlob->DomainName.Buffer =
|
||||
cpu_to_le32(SecurityBlobLength);
|
||||
bcc_ptr += len;
|
||||
SecurityBlobLength += len;
|
||||
SecurityBlob->DomainName.Length = cpu_to_le16(len);
|
||||
bcc_ptr += ln;
|
||||
SecurityBlobLength += ln;
|
||||
SecurityBlob->DomainName.Length = cpu_to_le16(ln);
|
||||
}
|
||||
if (user == NULL) {
|
||||
SecurityBlob->UserName.Buffer = 0;
|
||||
SecurityBlob->UserName.Length = 0;
|
||||
SecurityBlob->UserName.MaximumLength = 0;
|
||||
} else {
|
||||
__u16 len;
|
||||
__u16 ln;
|
||||
strncpy(bcc_ptr, user, 63);
|
||||
len = strnlen(user, 64);
|
||||
SecurityBlob->UserName.MaximumLength =
|
||||
cpu_to_le16(len);
|
||||
ln = strnlen(user, 64);
|
||||
SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
|
||||
SecurityBlob->UserName.Buffer =
|
||||
cpu_to_le32(SecurityBlobLength);
|
||||
bcc_ptr += len;
|
||||
SecurityBlobLength += len;
|
||||
SecurityBlob->UserName.Length = cpu_to_le16(len);
|
||||
cpu_to_le32(SecurityBlobLength);
|
||||
bcc_ptr += ln;
|
||||
SecurityBlobLength += ln;
|
||||
SecurityBlob->UserName.Length = cpu_to_le16(ln);
|
||||
}
|
||||
/* 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,
|
||||
&bytes_returned, 1);
|
||||
if (rc) {
|
||||
/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
|
||||
} else if ((smb_buffer_response->WordCount == 3)
|
||||
|| (smb_buffer_response->WordCount == 4)) {
|
||||
/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
|
||||
} else if ((smb_buffer_response->WordCount == 3) ||
|
||||
(smb_buffer_response->WordCount == 4)) {
|
||||
__u16 action = le16_to_cpu(pSMBr->resp.Action);
|
||||
__u16 blob_len =
|
||||
le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
||||
__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
||||
if (action & GUEST_LOGIN)
|
||||
cFYI(1, (" Guest login")); /* BB Should we set anything
|
||||
in SesInfo struct ? */
|
||||
@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
} else {
|
||||
remaining_words = BCC(smb_buffer_response) / 2;
|
||||
}
|
||||
len =
|
||||
UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
|
||||
len = UniStrnlen((wchar_t *) bcc_ptr,
|
||||
remaining_words - 1);
|
||||
/* 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
|
||||
terminating last Unicode string in response */
|
||||
@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
<= BCC(smb_buffer_response)) {
|
||||
if (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);
|
||||
|
||||
bcc_ptr += len;
|
||||
@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||
bcc_ptr[0] = 0;
|
||||
bcc_ptr++;
|
||||
} else
|
||||
cFYI(1,
|
||||
("field of length %d "
|
||||
cFYI(1, ("field of length %d "
|
||||
"extends beyond end of smb ",
|
||||
len));
|
||||
}
|
||||
} else {
|
||||
cERROR(1,
|
||||
(" Security Blob extends beyond end "
|
||||
cERROR(1, ("Security Blob extends beyond end "
|
||||
"of SMB"));
|
||||
}
|
||||
} else {
|
||||
cERROR(1, ("No session structure passed in."));
|
||||
}
|
||||
} else {
|
||||
cERROR(1,
|
||||
(" Invalid Word count %d: ",
|
||||
cERROR(1, ("Invalid Word count %d: ",
|
||||
smb_buffer_response->WordCount));
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
if (smb_buffer)
|
||||
cifs_buf_release(smb_buffer);
|
||||
cifs_buf_release(smb_buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
||||
bcc_ptr = pByteArea(smb_buffer_response);
|
||||
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
|
||||
/* 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;
|
||||
strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
|
||||
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
|
||||
@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
||||
kfree(tcon->nativeFileSystem);
|
||||
tcon->nativeFileSystem =
|
||||
kzalloc(length + 2, GFP_KERNEL);
|
||||
cifs_strfromUCS_le(tcon->nativeFileSystem,
|
||||
(__le16 *) bcc_ptr,
|
||||
length, nls_codepage);
|
||||
if (tcon->nativeFileSystem)
|
||||
cifs_strfromUCS_le(
|
||||
tcon->nativeFileSystem,
|
||||
(__le16 *) bcc_ptr,
|
||||
length, nls_codepage);
|
||||
bcc_ptr += 2 * length;
|
||||
bcc_ptr[0] = 0; /* null terminate the string */
|
||||
bcc_ptr[1] = 0;
|
||||
@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
||||
kfree(tcon->nativeFileSystem);
|
||||
tcon->nativeFileSystem =
|
||||
kzalloc(length + 1, GFP_KERNEL);
|
||||
strncpy(tcon->nativeFileSystem, bcc_ptr,
|
||||
length);
|
||||
if (tcon->nativeFileSystem)
|
||||
strncpy(tcon->nativeFileSystem, bcc_ptr,
|
||||
length);
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (smb_buffer)
|
||||
cifs_buf_release(smb_buffer);
|
||||
cifs_buf_release(smb_buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* vfs operations that deal with dentries
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
||||
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
@ -269,7 +269,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||
} else if (newinode) {
|
||||
pCifsFile =
|
||||
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
|
||||
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
||||
|
||||
if (pCifsFile == NULL)
|
||||
goto cifs_create_out;
|
||||
@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||
/* BB Do not bother to decode buf since no
|
||||
local inode yet to put timestamps in,
|
||||
but we can reuse it safely */
|
||||
int bytes_written;
|
||||
unsigned int bytes_written;
|
||||
struct win_dev *pdev;
|
||||
pdev = (struct win_dev *)buf;
|
||||
if (S_ISCHR(mode)) {
|
||||
@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
cFYI(1,
|
||||
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
|
||||
cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p",
|
||||
parent_dir_inode, direntry->d_name.name, direntry));
|
||||
|
||||
/* check whether path exists */
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <linux/exportfs.h>
|
||||
#include "cifsglob.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifsfs.h"
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
||||
|
@ -467,7 +467,7 @@ reopen_error_exit:
|
||||
int cifs_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
int rc = 0;
|
||||
int xid;
|
||||
int xid, timeout;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct cifsFileInfo *pSMBFile =
|
||||
@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||
/* no sense reconnecting to close a file that is
|
||||
already closed */
|
||||
if (pTcon->tidStatus != CifsNeedReconnect) {
|
||||
int timeout = 2;
|
||||
timeout = 2;
|
||||
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||
&& (timeout < 1000) ) {
|
||||
&& (timeout <= 2048)) {
|
||||
/* Give write a better chance to get to
|
||||
server ahead of the close. We do not
|
||||
want to add a wait_q here as it would
|
||||
@ -522,12 +522,30 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||
list_del(&pSMBFile->flist);
|
||||
list_del(&pSMBFile->tlist);
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
timeout = 10;
|
||||
/* We waited above to give the SMBWrite a chance to issue
|
||||
on the wire (so we do not get SMBWrite returning EBADF
|
||||
if writepages is racing with close. Note that writepages
|
||||
does not specify a file handle, so it is possible for a file
|
||||
to be opened twice, and the application close the "wrong"
|
||||
file handle - in these cases we delay long enough to allow
|
||||
the SMBWrite to get on the wire before the SMB Close.
|
||||
We allow total wait here over 45 seconds, more than
|
||||
oplock break time, and more than enough to allow any write
|
||||
to complete on the server, or to time out on the client */
|
||||
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||
&& (timeout <= 50000)) {
|
||||
cERROR(1, ("writes pending, delay free of handle"));
|
||||
msleep(timeout);
|
||||
timeout *= 8;
|
||||
}
|
||||
kfree(pSMBFile->search_resume_name);
|
||||
kfree(file->private_data);
|
||||
file->private_data = NULL;
|
||||
} else
|
||||
rc = -EBADF;
|
||||
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
if (list_empty(&(CIFS_I(inode)->openFileList))) {
|
||||
cFYI(1, ("closing last open instance for inode %p", inode));
|
||||
/* if the file is not open we do not know if we can cache info
|
||||
@ -535,6 +553,7 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||
CIFS_I(inode)->clientCanCacheRead = FALSE;
|
||||
CIFS_I(inode)->clientCanCacheAll = FALSE;
|
||||
}
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
|
||||
rc = CIFS_I(inode)->write_behind_rc;
|
||||
FreeXid(xid);
|
||||
@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||
mutex_lock(&fid->lock_mutex);
|
||||
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
||||
if (pfLock->fl_start <= li->offset &&
|
||||
length >= li->length) {
|
||||
(pfLock->fl_start + length) >=
|
||||
(li->offset + li->length)) {
|
||||
stored_rc = CIFSSMBLock(xid, pTcon,
|
||||
netfid,
|
||||
li->length, li->offset,
|
||||
@ -1022,6 +1042,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
||||
}
|
||||
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
refind_writable:
|
||||
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
||||
if (open_file->closePend)
|
||||
continue;
|
||||
@ -1029,24 +1050,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
||||
((open_file->pfile->f_flags & O_RDWR) ||
|
||||
(open_file->pfile->f_flags & O_WRONLY))) {
|
||||
atomic_inc(&open_file->wrtPending);
|
||||
|
||||
if (!open_file->invalidHandle) {
|
||||
/* found a good writable file */
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
return open_file;
|
||||
}
|
||||
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
if ((open_file->invalidHandle) &&
|
||||
(!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
|
||||
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
||||
/* if it fails, try another handle - might be */
|
||||
/* dangerous to hold up writepages with retry */
|
||||
if (rc) {
|
||||
cFYI(1,
|
||||
("failed on reopen file in wp"));
|
||||
/* Had to unlock since following call can block */
|
||||
rc = cifs_reopen_file(open_file->pfile, FALSE);
|
||||
if (!rc) {
|
||||
if (!open_file->closePend)
|
||||
return open_file;
|
||||
else { /* start over in case this was deleted */
|
||||
/* since the list could be modified */
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
/* can not use this handle, no write
|
||||
pending on this one after all */
|
||||
atomic_dec
|
||||
(&open_file->wrtPending);
|
||||
continue;
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
goto refind_writable;
|
||||
}
|
||||
}
|
||||
return open_file;
|
||||
|
||||
/* if it fails, try another handle if possible -
|
||||
(we can not do this if closePending since
|
||||
loop could be modified - in which case we
|
||||
have to start at the beginning of the list
|
||||
again. Note that it would be bad
|
||||
to hold up writepages here (rather than
|
||||
in caller) with continuous retries */
|
||||
cFYI(1, ("wp failed on reopen file"));
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
/* can not use this handle, no write
|
||||
pending on this one after all */
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
|
||||
if (open_file->closePend) /* list could have changed */
|
||||
goto refind_writable;
|
||||
/* else we simply continue to the next entry. Thus
|
||||
we do not loop on reopen errors. If we
|
||||
can not reopen the file, for example if we
|
||||
reconnected to a server with another client
|
||||
racing to delete or lock the file we would not
|
||||
make progress if we restarted before the beginning
|
||||
of the loop here. */
|
||||
}
|
||||
}
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
@ -1709,7 +1755,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||
struct page *page;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
int bytes_read = 0;
|
||||
unsigned int bytes_read = 0;
|
||||
unsigned int read_size, i;
|
||||
char *smb_read_data = NULL;
|
||||
struct smb_com_read_rsp *pSMBr;
|
||||
@ -1803,7 +1849,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||
|
||||
i += bytes_read >> PAGE_CACHE_SHIFT;
|
||||
cifs_stats_bytes_read(pTcon, bytes_read);
|
||||
if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
|
||||
if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
|
||||
i++; /* account for partial page */
|
||||
|
||||
/* server copy of file can have smaller size
|
||||
|
@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
inode->i_mode = le64_to_cpu(findData.Permissions);
|
||||
/* since we set the inode type below we need to mask off
|
||||
to avoid strange results if bits set above */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
if (type == UNIX_FILE) {
|
||||
inode->i_mode |= S_IFREG;
|
||||
} else if (type == UNIX_SYMLINK) {
|
||||
@ -575,19 +575,33 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct inode_operations cifs_ipc_inode_ops = {
|
||||
.lookup = cifs_lookup,
|
||||
};
|
||||
|
||||
/* gets root inode */
|
||||
void cifs_read_inode(struct inode *inode)
|
||||
{
|
||||
int xid;
|
||||
int xid, rc;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
xid = GetXid();
|
||||
|
||||
if (cifs_sb->tcon->unix_ext)
|
||||
cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
|
||||
rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
|
||||
else
|
||||
cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
|
||||
rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
|
||||
if (rc && cifs_sb->tcon->ipc) {
|
||||
cFYI(1, ("ipc connection - fake read inode"));
|
||||
inode->i_mode |= S_IFDIR;
|
||||
inode->i_nlink = 2;
|
||||
inode->i_op = &cifs_ipc_inode_ops;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
inode->i_uid = cifs_sb->mnt_uid;
|
||||
inode->i_gid = cifs_sb->mnt_gid;
|
||||
}
|
||||
|
||||
/* can not call macro FreeXid here since in a void func */
|
||||
_FreeXid(xid);
|
||||
}
|
||||
@ -919,18 +933,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
mode &= ~current->fs->umask;
|
||||
rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
|
||||
mode, NULL /* netfid */, pInfo, &oplock,
|
||||
full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
kfree(pInfo);
|
||||
goto mkdir_retry_old;
|
||||
} else if (rc) {
|
||||
cFYI(1, ("posix mkdir returned 0x%x", rc));
|
||||
d_drop(direntry);
|
||||
} else {
|
||||
int obj_type;
|
||||
if (pInfo->Type == -1) /* no return info - go query */
|
||||
if (pInfo->Type == cpu_to_le32(-1)) {
|
||||
/* no return info, go query for it */
|
||||
kfree(pInfo);
|
||||
goto mkdir_get_info;
|
||||
}
|
||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
|
||||
to set uid/gid */
|
||||
inc_nlink(inode);
|
||||
@ -940,8 +961,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
direntry->d_op = &cifs_dentry_ops;
|
||||
|
||||
newinode = new_inode(inode->i_sb);
|
||||
if (newinode == NULL)
|
||||
if (newinode == NULL) {
|
||||
kfree(pInfo);
|
||||
goto mkdir_get_info;
|
||||
}
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
@ -972,7 +995,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
kfree(pInfo);
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
mkdir_retry_old:
|
||||
/* BB add setting the equivalent of mode via CreateX w/ACLs */
|
||||
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
@ -1377,8 +1400,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset)
|
||||
}
|
||||
i_size_write(inode, offset);
|
||||
spin_unlock(&inode->i_lock);
|
||||
/*
|
||||
* unmap_mapping_range is called twice, first simply for efficiency
|
||||
* so that truncate_inode_pages does fewer single-page unmaps. However
|
||||
* after this first call, and before truncate_inode_pages finishes,
|
||||
* it is possible for private pages to be COWed, which remain after
|
||||
* truncate_inode_pages finishes, hence the second unmap_mapping_range
|
||||
* call must be made for correctness.
|
||||
*/
|
||||
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||
truncate_inode_pages(mapping, offset);
|
||||
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||
goto out_truncate;
|
||||
|
||||
do_expand:
|
||||
@ -1469,7 +1501,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
cFYI(1, ("SetFSize for attrs rc = %d", rc));
|
||||
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||
int bytes_written;
|
||||
unsigned int bytes_written;
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
nfid, 0, attrs->ia_size,
|
||||
&bytes_written, NULL, NULL,
|
||||
@ -1502,7 +1534,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc == 0) {
|
||||
int bytes_written;
|
||||
unsigned int bytes_written;
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
netfid, 0,
|
||||
attrs->ia_size,
|
||||
|
@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||
char *tmp_path = NULL;
|
||||
char *tmpbuffer;
|
||||
unsigned char *referrals = NULL;
|
||||
int num_referrals = 0;
|
||||
unsigned int num_referrals = 0;
|
||||
int len;
|
||||
__u16 fid;
|
||||
|
||||
|
@ -169,7 +169,6 @@ cifs_buf_get(void)
|
||||
void
|
||||
cifs_buf_release(void *buf_to_free)
|
||||
{
|
||||
|
||||
if (buf_to_free == NULL) {
|
||||
/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
|
||||
return;
|
||||
|
@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
|
||||
{ERRusempx, -EIO},
|
||||
{ERRusestd, -EIO},
|
||||
{ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
|
||||
{ERRaccountexpired, -EACCES},
|
||||
{ERRnoSuchUser, -EACCES},
|
||||
/* {ERRaccountexpired, -EACCES},
|
||||
{ERRbadclient, -EACCES},
|
||||
{ERRbadLogonTime, -EACCES},
|
||||
{ERRpasswordExpired, -EACCES},
|
||||
{ERRpasswordExpired, -EACCES},*/
|
||||
{ERRaccountexpired, -EKEYEXPIRED},
|
||||
{ERRbadclient, -EACCES},
|
||||
{ERRbadLogonTime, -EACCES},
|
||||
{ERRpasswordExpired, -EKEYEXPIRED},
|
||||
|
||||
{ERRnosupport, -EINVAL},
|
||||
{0, 0}
|
||||
};
|
||||
@ -270,7 +276,7 @@ static const struct {
|
||||
from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
|
||||
during the session setup } */
|
||||
{
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
|
||||
ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
|
||||
@ -285,10 +291,10 @@ static const struct {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
|
||||
ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
|
||||
ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
|
||||
ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
|
||||
ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
|
||||
ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
|
||||
ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
|
||||
ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
|
||||
@ -585,7 +591,7 @@ static const struct {
|
||||
ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
|
||||
ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
|
||||
ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
|
||||
ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
|
||||
ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
|
||||
@ -754,7 +760,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
|
||||
}
|
||||
|
||||
int
|
||||
map_smb_to_linux_error(struct smb_hdr *smb)
|
||||
map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
|
||||
{
|
||||
unsigned int i;
|
||||
int rc = -EIO; /* if transport error smb error may not be set */
|
||||
@ -771,7 +777,9 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||
/* translate the newer STATUS codes to old style SMB errors
|
||||
* and then to POSIX errors */
|
||||
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
||||
if (cifsFYI & CIFS_RC)
|
||||
if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
|
||||
cifs_print_status(err);
|
||||
else if (cifsFYI & CIFS_RC)
|
||||
cifs_print_status(err);
|
||||
ntstatus_to_dos(err, &smberrclass, &smberrcode);
|
||||
} else {
|
||||
@ -813,7 +821,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||
}
|
||||
/* else ERRHRD class errors or junk - return EIO */
|
||||
|
||||
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!",
|
||||
cFYI(1, ("Mapping smb error code %d to POSIX err %d",
|
||||
smberrcode, rc));
|
||||
|
||||
/* generic corrective action e.g. reconnect SMB session on
|
||||
@ -899,8 +907,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
|
||||
cERROR(1, ("illegal hours %d", st->Hours));
|
||||
days = sd->Day;
|
||||
month = sd->Month;
|
||||
if ((days > 31) || (month > 12))
|
||||
if ((days > 31) || (month > 12)) {
|
||||
cERROR(1, ("illegal date, month %d day: %d", month, days));
|
||||
if (month > 12)
|
||||
month = 12;
|
||||
}
|
||||
month -= 1;
|
||||
days += total_days_of_prev_months[month];
|
||||
days += 3652; /* account for difference in days between 1980 and 1970 */
|
||||
|
@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
|
||||
|
||||
|
||||
static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||
char *buf, int *pobject_type, int isNewInode)
|
||||
char *buf, unsigned int *pobject_type, int isNewInode)
|
||||
{
|
||||
loff_t local_size;
|
||||
struct timespec local_mtime;
|
||||
@ -294,7 +294,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||
}
|
||||
|
||||
static void unix_fill_in_inode(struct inode *tmp_inode,
|
||||
FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode)
|
||||
FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode)
|
||||
{
|
||||
loff_t local_size;
|
||||
struct timespec local_mtime;
|
||||
@ -826,7 +826,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
||||
int rc = 0;
|
||||
struct qstr qstring;
|
||||
struct cifsFileInfo *pCifsF;
|
||||
unsigned obj_type;
|
||||
unsigned int obj_type;
|
||||
ino_t inum;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct inode *tmp_inode;
|
||||
@ -1067,7 +1067,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
|
||||
if (current_entry == NULL) {
|
||||
/* evaluate whether this case is an error */
|
||||
cERROR(1,("past end of SMB num to fill %d i %d",
|
||||
cERROR(1, ("past SMB end, num to fill %d i %d",
|
||||
num_to_fill, i));
|
||||
break;
|
||||
}
|
||||
|
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;
|
||||
capabilities |= CAP_DFS;
|
||||
}
|
||||
if (ses->capabilities & CAP_UNIX) {
|
||||
if (ses->capabilities & CAP_UNIX)
|
||||
capabilities |= CAP_UNIX;
|
||||
}
|
||||
|
||||
/* BB check whether to init vcnum BB */
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
static void
|
||||
unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
|
||||
{
|
||||
char *bcc_ptr = *pbcc_area;
|
||||
int bytes_ret = 0;
|
||||
|
||||
/* Copy OS version */
|
||||
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
|
||||
nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
|
||||
32, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* trailing null */
|
||||
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
32, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* trailing null */
|
||||
|
||||
*pbcc_area = bcc_ptr;
|
||||
}
|
||||
|
||||
static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
char *bcc_ptr = *pbcc_area;
|
||||
int bytes_ret = 0;
|
||||
|
||||
/* copy domain */
|
||||
if (ses->domainName == NULL) {
|
||||
/* Sending null domain better than using a bogus domain name (as
|
||||
we did briefly in 2.6.18) since server will use its default */
|
||||
*bcc_ptr = 0;
|
||||
*(bcc_ptr+1) = 0;
|
||||
bytes_ret = 0;
|
||||
} else
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
|
||||
256, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* account for null terminator */
|
||||
|
||||
*pbcc_area = bcc_ptr;
|
||||
}
|
||||
|
||||
|
||||
static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
|
||||
const struct nls_table *nls_cp)
|
||||
{
|
||||
@ -100,32 +145,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
|
||||
}
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* account for null termination */
|
||||
/* copy domain */
|
||||
if (ses->domainName == NULL) {
|
||||
/* Sending null domain better than using a bogus domain name (as
|
||||
we did briefly in 2.6.18) since server will use its default */
|
||||
*bcc_ptr = 0;
|
||||
*(bcc_ptr+1) = 0;
|
||||
bytes_ret = 0;
|
||||
} else
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
|
||||
256, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* account for null terminator */
|
||||
|
||||
/* Copy OS version */
|
||||
bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
|
||||
nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
|
||||
32, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* trailing null */
|
||||
|
||||
bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
32, nls_cp);
|
||||
bcc_ptr += 2 * bytes_ret;
|
||||
bcc_ptr += 2; /* trailing null */
|
||||
unicode_domain_string(&bcc_ptr, ses, nls_cp);
|
||||
unicode_oslm_strings(&bcc_ptr, nls_cp);
|
||||
|
||||
*pbcc_area = bcc_ptr;
|
||||
}
|
||||
@ -203,14 +225,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
||||
if (len >= words_left)
|
||||
return rc;
|
||||
|
||||
if (ses->serverOS)
|
||||
kfree(ses->serverOS);
|
||||
kfree(ses->serverOS);
|
||||
/* UTF-8 string will not grow more than four times as big as UCS-16 */
|
||||
ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
|
||||
if (ses->serverOS != NULL) {
|
||||
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
|
||||
nls_cp);
|
||||
}
|
||||
if (ses->serverOS != NULL)
|
||||
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
|
||||
data += 2 * (len + 1);
|
||||
words_left -= len + 1;
|
||||
|
||||
@ -220,8 +239,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
||||
if (len >= words_left)
|
||||
return rc;
|
||||
|
||||
if (ses->serverNOS)
|
||||
kfree(ses->serverNOS);
|
||||
kfree(ses->serverNOS);
|
||||
ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
|
||||
if (ses->serverNOS != NULL) {
|
||||
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
|
||||
@ -240,8 +258,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
||||
if (len > words_left)
|
||||
return rc;
|
||||
|
||||
if (ses->serverDomain)
|
||||
kfree(ses->serverDomain);
|
||||
kfree(ses->serverDomain);
|
||||
ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
|
||||
if (ses->serverDomain != NULL) {
|
||||
cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
|
||||
@ -271,8 +288,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
|
||||
if (len >= bleft)
|
||||
return rc;
|
||||
|
||||
if (ses->serverOS)
|
||||
kfree(ses->serverOS);
|
||||
kfree(ses->serverOS);
|
||||
|
||||
ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
|
||||
if (ses->serverOS)
|
||||
@ -289,8 +305,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
|
||||
if (len >= bleft)
|
||||
return rc;
|
||||
|
||||
if (ses->serverNOS)
|
||||
kfree(ses->serverNOS);
|
||||
kfree(ses->serverNOS);
|
||||
|
||||
ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
|
||||
if (ses->serverNOS)
|
||||
@ -479,7 +494,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||
if (ses->capabilities & CAP_UNICODE) {
|
||||
if (iov[0].iov_len % 2) {
|
||||
*bcc_ptr = 0;
|
||||
} bcc_ptr++;
|
||||
bcc_ptr++;
|
||||
}
|
||||
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||
} else
|
||||
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
|
||||
@ -497,7 +513,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||
|
||||
iov[1].iov_base = str_area;
|
||||
iov[1].iov_len = count;
|
||||
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
|
||||
rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type,
|
||||
0 /* not long op */, 1 /* log NT STATUS if any */ );
|
||||
/* SMB request buf freed in SendReceive2 */
|
||||
|
||||
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
|
||||
|
@ -173,9 +173,10 @@
|
||||
#define ERRusestd 251 /* temporarily unable to use either raw
|
||||
or mpx */
|
||||
#define ERR_NOTIFY_ENUM_DIR 1024
|
||||
#define ERRnoSuchUser 2238 /* user account does not exist */
|
||||
#define ERRaccountexpired 2239
|
||||
#define ERRbadclient 2240
|
||||
#define ERRbadLogonTime 2241
|
||||
#define ERRbadclient 2240 /* can not logon from this client */
|
||||
#define ERRbadLogonTime 2241 /* logon hours do not allow this */
|
||||
#define ERRpasswordExpired 2242
|
||||
#define ERRnetlogonNotStarted 2455
|
||||
#define ERRnosupport 0xFFFF
|
||||
|
@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
|
||||
if (temp == NULL)
|
||||
return temp;
|
||||
else {
|
||||
memset(temp, 0, sizeof (struct mid_q_entry));
|
||||
memset(temp, 0, sizeof(struct mid_q_entry));
|
||||
temp->mid = smb_buffer->Mid; /* always LE */
|
||||
temp->pid = current->pid;
|
||||
temp->command = smb_buffer->Command;
|
||||
@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
|
||||
iov.iov_len = len;
|
||||
|
||||
smb_msg.msg_name = sin;
|
||||
smb_msg.msg_namelen = sizeof (struct sockaddr);
|
||||
smb_msg.msg_namelen = sizeof(struct sockaddr);
|
||||
smb_msg.msg_control = NULL;
|
||||
smb_msg.msg_controllen = 0;
|
||||
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
|
||||
@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
|
||||
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
||||
|
||||
smb_msg.msg_name = sin;
|
||||
smb_msg.msg_namelen = sizeof (struct sockaddr);
|
||||
smb_msg.msg_namelen = sizeof(struct sockaddr);
|
||||
smb_msg.msg_control = NULL;
|
||||
smb_msg.msg_controllen = 0;
|
||||
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
|
||||
@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
|
||||
} /* else ok - we are setting up session */
|
||||
}
|
||||
*ppmidQ = AllocMidQEntry(in_buf, ses);
|
||||
if (*ppmidQ == NULL) {
|
||||
if (*ppmidQ == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -419,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
|
||||
int
|
||||
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
|
||||
const int long_op)
|
||||
const int long_op, const int logError)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int receive_len;
|
||||
@ -465,7 +464,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
wake_up(&ses->server->request_q);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
|
||||
|
||||
midQ->midState = MID_REQUEST_SUBMITTED;
|
||||
@ -568,13 +566,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
}
|
||||
|
||||
/* BB special case reconnect tid and uid here? */
|
||||
/* BB special case Errbadpassword and pwdexpired here */
|
||||
rc = map_smb_to_linux_error(midQ->resp_buf);
|
||||
rc = map_smb_to_linux_error(midQ->resp_buf, logError);
|
||||
|
||||
/* convert ByteCount if necessary */
|
||||
if (receive_len >=
|
||||
sizeof (struct smb_hdr) -
|
||||
4 /* do not count RFC1001 header */ +
|
||||
if (receive_len >= sizeof(struct smb_hdr) - 4
|
||||
/* do not count RFC1001 header */ +
|
||||
(2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(midQ->resp_buf) =
|
||||
le16_to_cpu(BCC_LE(midQ->resp_buf));
|
||||
@ -749,12 +745,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||
*pbytes_returned = out_buf->smb_buf_length;
|
||||
|
||||
/* BB special case reconnect tid and uid here? */
|
||||
rc = map_smb_to_linux_error(out_buf);
|
||||
rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
|
||||
|
||||
/* convert ByteCount if necessary */
|
||||
if (receive_len >=
|
||||
sizeof (struct smb_hdr) -
|
||||
4 /* do not count RFC1001 header */ +
|
||||
if (receive_len >= sizeof(struct smb_hdr) - 4
|
||||
/* do not count RFC1001 header */ +
|
||||
(2 * out_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||
} else {
|
||||
@ -993,12 +988,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||
*pbytes_returned = out_buf->smb_buf_length;
|
||||
|
||||
/* BB special case reconnect tid and uid here? */
|
||||
rc = map_smb_to_linux_error(out_buf);
|
||||
rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
|
||||
|
||||
/* convert ByteCount if necessary */
|
||||
if (receive_len >=
|
||||
sizeof (struct smb_hdr) -
|
||||
4 /* do not count RFC1001 header */ +
|
||||
if (receive_len >= sizeof(struct smb_hdr) - 4
|
||||
/* do not count RFC1001 header */ +
|
||||
(2 * out_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||
} else {
|
||||
|
@ -261,21 +261,26 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
__u16 fid;
|
||||
int oplock = FALSE;
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
||||
FILE_OPEN, GENERIC_READ, 0, &fid,
|
||||
&oplock, NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (experimEnabled)
|
||||
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
||||
FILE_OPEN, GENERIC_READ, 0, &fid,
|
||||
&oplock, NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* else rc is EOPNOTSUPP from above */
|
||||
|
||||
if(rc == 0) {
|
||||
rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
|
||||
ea_value, buf_size,
|
||||
ACL_TYPE_ACCESS);
|
||||
CIFSSMBClose(xid, pTcon, fid);
|
||||
}
|
||||
} */ /* BB enable after fixing up return data */
|
||||
}
|
||||
#endif /* EXPERIMENTAL */
|
||||
#else
|
||||
cFYI(1, ("query POSIX ACL not supported yet"));
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
Loading…
Reference in New Issue
Block a user