Commit aada1bc9 authored by Linus Torvalds's avatar Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] remove unknown mount option warning message
  [CIFS] remove bkl usage from umount begin
  cifs: Fix incorrect return code being printed in cFYI messages
  [CIFS] cleanup asn handling for ntlmssp
  [CIFS] Copy struct *after* setting the port, instead of before.
  cifs: remove rw/ro options
  cifs: fix problems with earlier patches
  cifs: have cifs parse scope_id out of IPv6 addresses and use it
  [CIFS] Do not send tree disconnect if session is already disconnected
  [CIFS] Fix build break
  cifs: display scopeid in /proc/mounts
  cifs: add new routine for converting AF_INET and AF_INET6 addrs
  cifs: have cifs_show_options show forceuid/forcegid options
  cifs: remove unneeded NULL checks from cifs_show_options
parents 7e0d8a83 71a394fa
...@@ -5,7 +5,7 @@ client generated ones by default (mount option "serverino" turned ...@@ -5,7 +5,7 @@ client generated ones by default (mount option "serverino" turned
on by default if server supports it). Add forceuid and forcegid on by default if server supports it). Add forceuid and forcegid
mount options (so that when negotiating unix extensions specifying mount options (so that when negotiating unix extensions specifying
which uid mounted does not immediately force the server's reported which uid mounted does not immediately force the server's reported
uids to be overridden). uids to be overridden). Add support for scope moutn parm.
Version 1.58 Version 1.58
------------ ------------
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#define ASN1_OJI 6 /* Object Identifier */ #define ASN1_OJI 6 /* Object Identifier */
#define ASN1_OJD 7 /* Object Description */ #define ASN1_OJD 7 /* Object Description */
#define ASN1_EXT 8 /* External */ #define ASN1_EXT 8 /* External */
#define ASN1_ENUM 10 /* Enumerated */
#define ASN1_SEQ 16 /* Sequence */ #define ASN1_SEQ 16 /* Sequence */
#define ASN1_SET 17 /* Set */ #define ASN1_SET 17 /* Set */
#define ASN1_NUMSTR 18 /* Numerical String */ #define ASN1_NUMSTR 18 /* Numerical String */
...@@ -78,10 +79,12 @@ ...@@ -78,10 +79,12 @@
#define SPNEGO_OID_LEN 7 #define SPNEGO_OID_LEN 7
#define NTLMSSP_OID_LEN 10 #define NTLMSSP_OID_LEN 10
#define KRB5_OID_LEN 7 #define KRB5_OID_LEN 7
#define KRB5U2U_OID_LEN 8
#define MSKRB5_OID_LEN 7 #define MSKRB5_OID_LEN 7
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 }; static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 };
static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 }; static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
/* /*
...@@ -122,6 +125,28 @@ asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) ...@@ -122,6 +125,28 @@ asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
return 1; return 1;
} }
#if 0 /* will be needed later by spnego decoding/encoding of ntlmssp */
static unsigned char
asn1_enum_decode(struct asn1_ctx *ctx, __le32 *val)
{
unsigned char ch;
if (ctx->pointer >= ctx->end) {
ctx->error = ASN1_ERR_DEC_EMPTY;
return 0;
}
ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to lenght octet */
if ((ch) == ASN1_ENUM) /* if ch value is ENUM, 0xa */
*val = *(++(ctx->pointer)); /* value has enum value */
else
return 0;
ctx->pointer++;
return 1;
}
#endif
static unsigned char static unsigned char
asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
{ {
...@@ -476,10 +501,9 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -476,10 +501,9 @@ decode_negTokenInit(unsigned char *security_blob, int length,
unsigned int cls, con, tag, oidlen, rc; unsigned int cls, con, tag, oidlen, rc;
bool use_ntlmssp = false; bool use_ntlmssp = false;
bool use_kerberos = false; bool use_kerberos = false;
bool use_kerberosu2u = false;
bool use_mskerberos = false; bool use_mskerberos = false;
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
asn1_open(&ctx, security_blob, length); asn1_open(&ctx, security_blob, length);
...@@ -515,6 +539,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -515,6 +539,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} }
/* SPNEGO */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding negTokenInit")); cFYI(1, ("Error decoding negTokenInit"));
return 0; return 0;
...@@ -526,6 +551,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -526,6 +551,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} }
/* negTokenInit */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding negTokenInit")); cFYI(1, ("Error decoding negTokenInit"));
return 0; return 0;
...@@ -537,6 +563,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -537,6 +563,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} }
/* sequence */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding 2nd part of negTokenInit")); cFYI(1, ("Error decoding 2nd part of negTokenInit"));
return 0; return 0;
...@@ -548,6 +575,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -548,6 +575,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} }
/* sequence of */
if (asn1_header_decode if (asn1_header_decode
(&ctx, &sequence_end, &cls, &con, &tag) == 0) { (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding 2nd part of negTokenInit")); cFYI(1, ("Error decoding 2nd part of negTokenInit"));
...@@ -560,6 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -560,6 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
return 0; return 0;
} }
/* list of security mechanisms */
while (!asn1_eoc_decode(&ctx, sequence_end)) { while (!asn1_eoc_decode(&ctx, sequence_end)) {
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (!rc) { if (!rc) {
...@@ -576,11 +605,15 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -576,11 +605,15 @@ decode_negTokenInit(unsigned char *security_blob, int length,
if (compare_oid(oid, oidlen, MSKRB5_OID, if (compare_oid(oid, oidlen, MSKRB5_OID,
MSKRB5_OID_LEN) && MSKRB5_OID_LEN) &&
!use_kerberos) !use_mskerberos)
use_mskerberos = true; use_mskerberos = true;
else if (compare_oid(oid, oidlen, KRB5U2U_OID,
KRB5U2U_OID_LEN) &&
!use_kerberosu2u)
use_kerberosu2u = true;
else if (compare_oid(oid, oidlen, KRB5_OID, else if (compare_oid(oid, oidlen, KRB5_OID,
KRB5_OID_LEN) && KRB5_OID_LEN) &&
!use_mskerberos) !use_kerberos)
use_kerberos = true; use_kerberos = true;
else if (compare_oid(oid, oidlen, NTLMSSP_OID, else if (compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN)) NTLMSSP_OID_LEN))
...@@ -593,7 +626,12 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -593,7 +626,12 @@ decode_negTokenInit(unsigned char *security_blob, int length,
} }
} }
/* mechlistMIC */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
/* Check if we have reached the end of the blob, but with
no mechListMic (e.g. NTLMSSP instead of KRB5) */
if (ctx.error == ASN1_ERR_DEC_EMPTY)
goto decode_negtoken_exit;
cFYI(1, ("Error decoding last part negTokenInit exit3")); cFYI(1, ("Error decoding last part negTokenInit exit3"));
return 0; return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
...@@ -602,6 +640,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -602,6 +640,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
cls, con, tag, end, *end)); cls, con, tag, end, *end));
return 0; return 0;
} }
/* sequence */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding last part negTokenInit exit5")); cFYI(1, ("Error decoding last part negTokenInit exit5"));
return 0; return 0;
...@@ -611,6 +651,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -611,6 +651,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
cls, con, tag, end, *end)); cls, con, tag, end, *end));
} }
/* sequence of */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding last part negTokenInit exit 7")); cFYI(1, ("Error decoding last part negTokenInit exit 7"));
return 0; return 0;
...@@ -619,6 +660,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -619,6 +660,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
cls, con, tag, end, *end)); cls, con, tag, end, *end));
return 0; return 0;
} }
/* general string */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("Error decoding last part negTokenInit exit9")); cFYI(1, ("Error decoding last part negTokenInit exit9"));
return 0; return 0;
...@@ -630,13 +673,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -630,13 +673,13 @@ decode_negTokenInit(unsigned char *security_blob, int length,
} }
cFYI(1, ("Need to call asn1_octets_decode() function for %s", cFYI(1, ("Need to call asn1_octets_decode() function for %s",
ctx.pointer)); /* is this UTF-8 or ASCII? */ ctx.pointer)); /* is this UTF-8 or ASCII? */
decode_negtoken_exit:
if (use_kerberos) if (use_kerberos)
*secType = Kerberos; *secType = Kerberos;
else if (use_mskerberos) else if (use_mskerberos)
*secType = MSKerberos; *secType = MSKerberos;
else if (use_ntlmssp) else if (use_ntlmssp)
*secType = NTLMSSP; *secType = RawNTLMSSP;
return 1; return 1;
} }
...@@ -333,6 +333,27 @@ cifs_destroy_inode(struct inode *inode) ...@@ -333,6 +333,27 @@ cifs_destroy_inode(struct inode *inode)
kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
} }
static void
cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
{
seq_printf(s, ",addr=");
switch (server->addr.sockAddr.sin_family) {
case AF_INET:
seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr);
break;
case AF_INET6:
seq_printf(s, "%pI6",
&server->addr.sockAddr6.sin6_addr.s6_addr);
if (server->addr.sockAddr6.sin6_scope_id)
seq_printf(s, "%%%u",
server->addr.sockAddr6.sin6_scope_id);
break;
default:
seq_printf(s, "(unknown)");
}
}
/* /*
* cifs_show_options() is for displaying mount options in /proc/mounts. * cifs_show_options() is for displaying mount options in /proc/mounts.
* Not all settable options are displayed but most of the important * Not all settable options are displayed but most of the important
...@@ -343,83 +364,64 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) ...@@ -343,83 +364,64 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
{ {
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
struct TCP_Server_Info *server;
cifs_sb = CIFS_SB(m->mnt_sb); cifs_sb = CIFS_SB(m->mnt_sb);
tcon = cifs_sb->tcon;
if (cifs_sb) { seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
tcon = cifs_sb->tcon; if (tcon->ses->userName)
if (tcon) { seq_printf(s, ",username=%s", tcon->ses->userName);
seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); if (tcon->ses->domainName)
if (tcon->ses) { seq_printf(s, ",domain=%s", tcon->ses->domainName);
if (tcon->ses->userName)
seq_printf(s, ",username=%s", seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
tcon->ses->userName); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
if (tcon->ses->domainName) seq_printf(s, ",forceuid");
seq_printf(s, ",domain=%s",
tcon->ses->domainName); seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
server = tcon->ses->server; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
if (server) { seq_printf(s, ",forcegid");
seq_printf(s, ",addr=");
switch (server->addr.sockAddr6. cifs_show_address(s, tcon->ses->server);
sin6_family) {
case AF_INET6: if (!tcon->unix_ext)
seq_printf(s, "%pI6", seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
&server->addr.sockAddr6.sin6_addr);
break;
case AF_INET:
seq_printf(s, "%pI4",
&server->addr.sockAddr.sin_addr.s_addr);
break;
}
}
}
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
!(tcon->unix_ext))
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
!(tcon->unix_ext))
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
if (!tcon->unix_ext) {
seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
cifs_sb->mnt_file_mode, cifs_sb->mnt_file_mode,
cifs_sb->mnt_dir_mode); cifs_sb->mnt_dir_mode);
} if (tcon->seal)
if (tcon->seal) seq_printf(s, ",seal");
seq_printf(s, ",seal"); if (tcon->nocase)
if (tcon->nocase) seq_printf(s, ",nocase");
seq_printf(s, ",nocase"); if (tcon->retry)
if (tcon->retry) seq_printf(s, ",hard");
seq_printf(s, ",hard"); if (cifs_sb->prepath)
} seq_printf(s, ",prepath=%s", cifs_sb->prepath);
if (cifs_sb->prepath) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_printf(s, ",prepath=%s", cifs_sb->prepath); seq_printf(s, ",posixpaths");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
seq_printf(s, ",posixpaths"); seq_printf(s, ",setuids");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
seq_printf(s, ",setuids"); seq_printf(s, ",serverino");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
seq_printf(s, ",serverino"); seq_printf(s, ",directio");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
seq_printf(s, ",directio"); seq_printf(s, ",nouser_xattr");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
seq_printf(s, ",nouser_xattr"); seq_printf(s, ",mapchars");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
seq_printf(s, ",mapchars"); seq_printf(s, ",sfu");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
seq_printf(s, ",sfu"); seq_printf(s, ",nobrl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
seq_printf(s, ",nobrl"); seq_printf(s, ",cifsacl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
seq_printf(s, ",cifsacl"); seq_printf(s, ",dynperm");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) if (m->mnt_sb->s_flags & MS_POSIXACL)
seq_printf(s, ",dynperm"); seq_printf(s, ",acl");
if (m->mnt_sb->s_flags & MS_POSIXACL)
seq_printf(s, ",acl"); seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
}
return 0; return 0;
} }
...@@ -535,9 +537,14 @@ static void cifs_umount_begin(struct super_block *sb) ...@@ -535,9 +537,14 @@ static void cifs_umount_begin(struct super_block *sb)
if (tcon == NULL) if (tcon == NULL)
return; return;
lock_kernel();
read_lock(&cifs_tcp_ses_lock); read_lock(&cifs_tcp_ses_lock);
if (tcon->tc_count == 1) if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
/* we have other mounts to same share or we have
already tried to force umount this and woken up
all waiting network requests, nothing to do */
read_unlock(&cifs_tcp_ses_lock);
return;
} else if (tcon->tc_count == 1)
tcon->tidStatus = CifsExiting; tcon->tidStatus = CifsExiting;
read_unlock(&cifs_tcp_ses_lock); read_unlock(&cifs_tcp_ses_lock);
...@@ -552,9 +559,7 @@ static void cifs_umount_begin(struct super_block *sb) ...@@ -552,9 +559,7 @@ static void cifs_umount_begin(struct super_block *sb)
wake_up_all(&tcon->ses->server->response_q); wake_up_all(&tcon->ses->server->response_q);
msleep(1); msleep(1);
} }
/* BB FIXME - finish add checks for tidStatus BB */
unlock_kernel();
return; return;
} }
......
...@@ -83,7 +83,7 @@ enum securityEnum { ...@@ -83,7 +83,7 @@ enum securityEnum {
NTLM, /* Legacy NTLM012 auth with NTLM hash */ NTLM, /* Legacy NTLM012 auth with NTLM hash */
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */ /* NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */
Kerberos, /* Kerberos via SPNEGO */ Kerberos, /* Kerberos via SPNEGO */
MSKerberos, /* MS Kerberos via SPNEGO */ MSKerberos, /* MS Kerberos via SPNEGO */
}; };
......
...@@ -74,7 +74,7 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr); ...@@ -74,7 +74,7 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType); enum securityEnum *secType);
extern int cifs_inet_pton(const int, const char *source, void *dst); extern int cifs_convert_address(char *src, void *dst);
extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ , extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of const struct cifsTconInfo *, int /* length of
......
...@@ -594,7 +594,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -594,7 +594,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
else if (secFlags & CIFSSEC_MAY_KRB5) else if (secFlags & CIFSSEC_MAY_KRB5)
server->secType = Kerberos; server->secType = Kerberos;
else if (secFlags & CIFSSEC_MAY_NTLMSSP) else if (secFlags & CIFSSEC_MAY_NTLMSSP)
server->secType = NTLMSSP; server->secType = RawNTLMSSP;
else if (secFlags & CIFSSEC_MAY_LANMAN) else if (secFlags & CIFSSEC_MAY_LANMAN)
server->secType = LANMAN; server->secType = LANMAN;
/* #ifdef CONFIG_CIFS_EXPERIMENTAL /* #ifdef CONFIG_CIFS_EXPERIMENTAL
...@@ -729,7 +729,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) ...@@ -729,7 +729,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
* the tcon is no longer on the list, so no need to take lock before * the tcon is no longer on the list, so no need to take lock before
* checking this. * checking this.
*/ */
if (tcon->need_reconnect) if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
return 0; return 0;
rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
......
...@@ -70,7 +70,6 @@ struct smb_vol { ...@@ -70,7 +70,6 @@ struct smb_vol {
mode_t file_mode; mode_t file_mode;
mode_t dir_mode; mode_t dir_mode;
unsigned secFlg; unsigned secFlg;
bool rw:1;
bool retry:1; bool retry:1;
bool intr:1; bool intr:1;
bool setuids:1; bool setuids:1;
...@@ -832,7 +831,6 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -832,7 +831,6 @@ cifs_parse_mount_options(char *options, const char *devname,
vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = true;
/* default is always to request posix paths. */ /* default is always to request posix paths. */
vol->posix_paths = 1; vol->posix_paths = 1;
/* default to using server inode numbers where available */ /* default to using server inode numbers where available */
...@@ -1199,7 +1197,9 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -1199,7 +1197,9 @@ cifs_parse_mount_options(char *options, const char *devname,
} else if (strnicmp(data, "guest", 5) == 0) { } else if (strnicmp(data, "guest", 5) == 0) {
/* ignore */ /* ignore */
} else if (strnicmp(data, "rw", 2) == 0) { } else if (strnicmp(data, "rw", 2) == 0) {
vol->rw = true; /* ignore */
} else if (strnicmp(data, "ro", 2) == 0) {
/* ignore */
} else if (strnicmp(data, "noblocksend", 11) == 0) { } else if (strnicmp(data, "noblocksend", 11) == 0) {
vol->noblocksnd = 1; vol->noblocksnd = 1;
} else if (strnicmp(data, "noautotune", 10) == 0) { } else if (strnicmp(data, "noautotune", 10) == 0) {
...@@ -1218,8 +1218,6 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -1218,8 +1218,6 @@ cifs_parse_mount_options(char *options, const char *devname,
parse these options again and set anything and it parse these options again and set anything and it
is ok to just ignore them */ is ok to just ignore them */
continue; continue;
} else if (strnicmp(data, "ro", 2) == 0) {
vol->rw = false;
} else if (strnicmp(data, "hard", 4) == 0) { } else if (strnicmp(data, "hard", 4) == 0) {
vol->retry = 1; vol->retry = 1;
} else if (strnicmp(data, "soft", 4) == 0) { } else if (strnicmp(data, "soft", 4) == 0) {
...@@ -1386,8 +1384,10 @@ cifs_find_tcp_session(struct sockaddr_storage *addr) ...@@ -1386,8 +1384,10 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
server->addr.sockAddr.sin_addr.s_addr)) server->addr.sockAddr.sin_addr.s_addr))
continue; continue;
else if (addr->ss_family == AF_INET6 && else if (addr->ss_family == AF_INET6 &&
!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
&addr6->sin6_addr)) &addr6->sin6_addr) ||
server->addr.sockAddr6.sin6_scope_id !=
addr6->sin6_scope_id))
continue; continue;
++server->srv_count; ++server->srv_count;
...@@ -1433,28 +1433,15 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ...@@ -1433,28 +1433,15 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
memset(&addr, 0, sizeof(struct sockaddr_storage)); memset(&addr, 0, sizeof(struct sockaddr_storage));
if (volume_info->UNCip && volume_info->UNC) { cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip));
rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
&sin_server->sin_addr.s_addr);
if (rc <= 0) {
/* not ipv4 address, try ipv6 */
rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
&sin_server6->sin6_addr.in6_u);
if (rc > 0)
addr.ss_family = AF_INET6;
} else {
addr.ss_family = AF_INET;
}
if (rc <= 0) { if (volume_info->UNCip && volume_info->UNC) {
rc = cifs_convert_address(volume_info->UNCip, &addr);
if (!rc) {
/* we failed translating address */ /* we failed translating address */
rc = -EINVAL; rc = -EINVAL;
goto out_err; goto out_err;
} }
cFYI(1, ("UNC: %s ip: %s", volume_info->UNC,
volume_info->UNCip));
} else if (volume_info->UNCip) { } else if (volume_info->UNCip) {
/* BB using ip addr as tcp_ses name to connect to the /* BB using ip addr as tcp_ses name to connect to the
DFS root below */ DFS root below */
...@@ -1513,14 +1500,14 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ...@@ -1513,14 +1500,14 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
cFYI(1, ("attempting ipv6 connect")); cFYI(1, ("attempting ipv6 connect"));
/* BB should we allow ipv6 on port 139? */ /* BB should we allow ipv6 on port 139? */
/* other OS never observed in Wild doing 139 with v6 */ /* other OS never observed in Wild doing 139 with v6 */
sin_server6->sin6_port = htons(volume_info->port);
memcpy(&tcp_ses->addr.sockAddr6, sin_server6, memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
sizeof(struct sockaddr_in6)); sizeof(struct sockaddr_in6));
sin_server6->sin6_port = htons(volume_info->port);
rc = ipv6_connect(tcp_ses); rc = ipv6_connect(tcp_ses);
} else { } else {
sin_server->sin_port = htons(volume_info->port);
memcpy(&tcp_ses->addr.sockAddr, sin_server, memcpy(&tcp_ses->addr.sockAddr, sin_server,
sizeof(struct sockaddr_in)); sizeof(struct sockaddr_in));
sin_server->sin_port = htons(volume_info->port);
rc = ipv4_connect(tcp_ses); rc = ipv4_connect(tcp_ses);
} }
if (rc < 0) { if (rc < 0) {
......
...@@ -307,8 +307,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -307,8 +307,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
if (oplockEnabled) if (oplockEnabled)
...@@ -540,8 +541,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -540,8 +541,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) { if (buf == NULL) {
kfree(full_path); kfree(full_path);
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
rc = CIFSSMBOpen(xid, pTcon, full_path, rc = CIFSSMBOpen(xid, pTcon, full_path,
......
...@@ -35,26 +35,11 @@ ...@@ -35,26 +35,11 @@
* 0 - name is not IP * 0 - name is not IP
*/ */
static int static int
is_ip(const char *name) is_ip(char *name)
{ {
int rc; struct sockaddr_storage ss;
struct sockaddr_in sin_server;
struct sockaddr_in6 sin_server6; return cifs_convert_address(name, &ss);
rc = cifs_inet_pton(AF_INET, name,
&sin_server.sin_addr.s_addr);
if (rc <= 0) {
/* not ipv4 address, try ipv6 */
rc = cifs_inet_pton(AF_INET6, name,
&sin_server6.sin6_addr.in6_u);
if (rc > 0)
return 1;
} else {
return 1;
}
/* we failed translating address */
return 0;
} }
static int static int
...@@ -72,7 +57,7 @@ dns_resolver_instantiate(struct key *key, const void *data, ...@@ -72,7 +57,7 @@ dns_resolver_instantiate(struct key *key, const void *data,
ip[datalen] = '\0'; ip[datalen] = '\0';
/* make sure this looks like an address */ /* make sure this looks like an address */
if (!is_ip((const char *) ip)) { if (!is_ip(ip)) {
kfree(ip); kfree(ip);
return -EINVAL; return -EINVAL;
} }
......
...@@ -300,14 +300,16 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -300,14 +300,16 @@ int cifs_open(struct inode *inode, struct file *file)
pCifsInode = CIFS_I(file->f_path.dentry->d_inode); pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
pCifsFile = cifs_fill_filedata(file); pCifsFile = cifs_fill_filedata(file);
if (pCifsFile) { if (pCifsFile) {
rc = 0;
FreeXid(xid); FreeXid(xid);
return 0; return rc;
} }
full_path = build_path_from_dentry(file->f_path.dentry); full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
...@@ -494,8 +496,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush) ...@@ -494,8 +496,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
mutex_unlock(&pCifsFile->fh_mutex); mutex_unlock(&pCifsFile->fh_mutex);
if (!pCifsFile->invalidHandle) { if (!pCifsFile->invalidHandle) {
mutex_lock(&pCifsFile->fh_mutex); mutex_lock(&pCifsFile->fh_mutex);
rc = 0;
FreeXid(xid); FreeXid(xid);
return 0; return rc;
} }
if (file->f_path.dentry == NULL) { if (file->f_path.dentry == NULL) {
...@@ -845,8 +848,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -845,8 +848,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
tcon = cifs_sb->tcon; tcon = cifs_sb->tcon;
if (file->private_data == NULL) { if (file->private_data == NULL) {
rc = -EBADF;
FreeXid(xid); FreeXid(xid);
return -EBADF; return rc;
} }
netfid = ((struct cifsFileInfo *)file->private_data)->netfid; netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
...@@ -1805,8 +1809,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, ...@@ -1805,8 +1809,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
if (file->private_data == NULL) { if (file->private_data == NULL) {
rc = -EBADF;
FreeXid(xid); FreeXid(xid);
return -EBADF; return rc;
} }
open_file = (struct cifsFileInfo *)file->private_data; open_file = (struct cifsFileInfo *)file->private_data;
...@@ -1885,8 +1890,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, ...@@ -1885,8 +1890,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
if (file->private_data == NULL) { if (file->private_data == NULL) {
rc = -EBADF;
FreeXid(xid); FreeXid(xid);
return -EBADF; return rc;
} }
open_file = (struct cifsFileInfo *)file->private_data; open_file = (struct cifsFileInfo *)file->private_data;
...@@ -2019,8 +2025,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -2019,8 +2025,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
xid = GetXid(); xid = GetXid();
if (file->private_data == NULL) { if (file->private_data == NULL) {
rc = -EBADF;
FreeXid(xid); FreeXid(xid);
return -EBADF; return rc;
} }
open_file = (struct cifsFileInfo *)file->private_data; open_file = (struct cifsFileInfo *)file->private_data;
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
...@@ -2185,8 +2192,9 @@ static int cifs_readpage(struct file *file, struct page *page) ...@@ -2185,8 +2192,9 @@ static int cifs_readpage(struct file *file, struct page *page)
xid = GetXid(); xid = GetXid();
if (file->private_data == NULL) { if (file->private_data == NULL) {
rc = -EBADF;
FreeXid(xid); FreeXid(xid);
return -EBADF; return rc;
} }
cFYI(1, ("readpage %p at offset %d 0x%x\n", cFYI(1, ("readpage %p at offset %d 0x%x\n",
......
...@@ -988,8 +988,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -988,8 +988,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
* sb->s_vfs_rename_mutex here */ * sb->s_vfs_rename_mutex here */
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
if ((tcon->ses->capabilities & CAP_UNIX) && if ((tcon->ses->capabilities & CAP_UNIX) &&
...@@ -1118,8 +1119,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -1118,8 +1119,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
if ((pTcon->ses->capabilities & CAP_UNIX) && if ((pTcon->ses->capabilities & CAP_UNIX) &&
...@@ -1303,8 +1305,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1303,8 +1305,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
...@@ -1508,8 +1511,9 @@ int cifs_revalidate(struct dentry *direntry) ...@@ -1508,8 +1511,9 @@ int cifs_revalidate(struct dentry *direntry)
since that would deadlock */ since that would deadlock */
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
"jiffies %ld", full_path, direntry->d_inode, "jiffies %ld", full_path, direntry->d_inode,
...@@ -1911,8 +1915,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -1911,8 +1915,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
/* /*
......
...@@ -172,8 +172,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -172,8 +172,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
cFYI(1, ("Full path: %s", full_path)); cFYI(1, ("Full path: %s", full_path));
......
...@@ -133,10 +133,12 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { ...@@ -133,10 +133,12 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
{0, 0} {0, 0}
}; };
/* Convert string containing dotted ip address to binary form */ /*
/* returns 0 if invalid address */ * Convert a string containing text IPv4 or IPv6 address to binary form.
*
int * Returns 0 on failure.
*/
static int
cifs_inet_pton(const int address_family, const char *cp, void *dst) cifs_inet_pton(const int address_family, const char *cp, void *dst)
{ {
int ret = 0; int ret = 0;
...@@ -153,6 +155,52 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) ...@@ -153,6 +155,52 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst)
return ret; return ret;
} }
/*
* Try to convert a string to an IPv4 address and then attempt to convert
* it to an IPv6 address if that fails. Set the family field if either
* succeeds. If it's an IPv6 address and it has a '%' sign in it, try to
* treat the part following it as a numeric sin6_scope_id.
*
* Returns 0 on failure.
*/
int
cifs_convert_address(char *src, void *dst)
{
int rc;
char *pct, *endp;
struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
/* IPv4 address */
if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) {
s4->sin_family = AF_INET;
return 1;
}
/* temporarily terminate string */
pct = strchr(src, '%');
if (pct)
*pct = '\0';
rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr);
/* repair temp termination (if any) and make pct point to scopeid */
if (pct)
*pct++ = '%';
if (!rc)
return rc;
s6->sin6_family = AF_INET6;
if (pct) {
s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0);
if (!*pct || *endp)
return 0;
}
return rc;
}
/***************************************************************************** /*****************************************************************************
convert a NT status code to a dos class/code convert a NT status code to a dos class/code
*****************************************************************************/ *****************************************************************************/
......
...@@ -802,7 +802,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ...@@ -802,7 +802,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
#endif /* CONFIG_CIFS_UPCALL */ #endif /* CONFIG_CIFS_UPCALL */
} else { } else {
#ifdef CONFIG_CIFS_EXPERIMENTAL #ifdef CONFIG_CIFS_EXPERIMENTAL
if ((experimEnabled > 1) && (type == RawNTLMSSP)) { if (type == RawNTLMSSP) {
if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
cERROR(1, ("NTLMSSP requires Unicode support")); cERROR(1, ("NTLMSSP requires Unicode support"));
rc = -ENOSYS; rc = -ENOSYS;
......
...@@ -64,8 +64,9 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) ...@@ -64,8 +64,9 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
if (ea_name == NULL) { if (ea_name == NULL) {
cFYI(1, ("Null xattr names not supported")); cFYI(1, ("Null xattr names not supported"));
...@@ -118,8 +119,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ...@@ -118,8 +119,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
...@@ -225,8 +227,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, ...@@ -225,8 +227,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
...@@ -351,8 +354,9 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ...@@ -351,8 +354,9 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM;
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return rc;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */ /* return alt name if available as pseudo attr */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment