Skip to content

Commit e0b1f59

Browse files
committed
Merge tag 'v6.14-rc-smb3-client-fixes-part' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client updates from Steve French: - Fix oops in DebugData when link speed 0 - Two reparse point fixes - Ten DFS (global namespace) fixes - Symlink error handling fix - Two SMB1 fixes - Four cleanup fixes - Improved debugging of status codes - Fix incorrect output of tracepoints for compounding, and add missing compounding tracepoint * tag 'v6.14-rc-smb3-client-fixes-part' of git://git.samba.org/sfrench/cifs-2.6: (23 commits) smb: client: handle lack of EA support in smb2_query_path_info() smb: client: don't check for @leaf_fullpath in match_server() smb: client: get rid of TCP_Server_Info::refpath_lock cifs: Remove duplicate struct reparse_symlink_data and SYMLINK_FLAG_RELATIVE cifs: Do not attempt to call CIFSGetSrvInodeNumber() without CAP_INFOLEVEL_PASSTHRU cifs: Do not attempt to call CIFSSMBRenameOpenFile() without CAP_INFOLEVEL_PASSTHRU cifs: Remove declaration of dead CIFSSMBQuerySymLink function cifs: Fix printing Status code into dmesg cifs: Add missing NT_STATUS_* codes from nterr.h to nterr.c cifs: Fix endian types in struct rfc1002_session_packet cifs: Use cifs_autodisable_serverino() for disabling CIFS_MOUNT_SERVER_INUM in readdir.c smb3: add missing tracepoint for querying wsl EAs smb: client: fix order of arguments of tracepoints smb: client: fix oops due to unset link speed smb: client: correctly handle ErrorContextData as a flexible array smb: client: don't retry DFS targets on server shutdown smb: client: fix return value of parse_dfs_referrals() smb: client: optimize referral walk on failed link targets smb: client: provide dns_resolve_{unc,name} helpers smb: client: parse DNS domain name from domain= option ...
2 parents e814f3f + 3681c74 commit e0b1f59

25 files changed

+483
-436
lines changed

fs/smb/client/cifsencrypt.c

Lines changed: 82 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -315,59 +315,72 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
315315
return 0;
316316
}
317317

318-
/* Server has provided av pairs/target info in the type 2 challenge
319-
* packet and we have plucked it and stored within smb session.
320-
* We parse that blob here to find netbios domain name to be used
321-
* as part of ntlmv2 authentication (in Target String), if not already
322-
* specified on the command line.
323-
* If this function returns without any error but without fetching
324-
* domain name, authentication may fail against some server but
325-
* may not fail against other (those who are not very particular
326-
* about target string i.e. for some, just user name might suffice.
318+
#define AV_TYPE(av) (le16_to_cpu(av->type))
319+
#define AV_LEN(av) (le16_to_cpu(av->length))
320+
#define AV_DATA_PTR(av) ((void *)av->data)
321+
322+
#define av_for_each_entry(ses, av) \
323+
for (av = NULL; (av = find_next_av(ses, av));)
324+
325+
static struct ntlmssp2_name *find_next_av(struct cifs_ses *ses,
326+
struct ntlmssp2_name *av)
327+
{
328+
u16 len;
329+
u8 *end;
330+
331+
end = (u8 *)ses->auth_key.response + ses->auth_key.len;
332+
if (!av) {
333+
if (unlikely(!ses->auth_key.response || !ses->auth_key.len))
334+
return NULL;
335+
av = (void *)ses->auth_key.response;
336+
} else {
337+
av = (void *)((u8 *)av + sizeof(*av) + AV_LEN(av));
338+
}
339+
340+
if ((u8 *)av + sizeof(*av) > end)
341+
return NULL;
342+
343+
len = AV_LEN(av);
344+
if (AV_TYPE(av) == NTLMSSP_AV_EOL)
345+
return NULL;
346+
if (!len || (u8 *)av + sizeof(*av) + len > end)
347+
return NULL;
348+
return av;
349+
}
350+
351+
/*
352+
* Check if server has provided av pair of @type in the NTLMSSP
353+
* CHALLENGE_MESSAGE blob.
327354
*/
328-
static int
329-
find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
355+
static int find_av_name(struct cifs_ses *ses, u16 type, char **name, u16 maxlen)
330356
{
331-
unsigned int attrsize;
332-
unsigned int type;
333-
unsigned int onesize = sizeof(struct ntlmssp2_name);
334-
unsigned char *blobptr;
335-
unsigned char *blobend;
336-
struct ntlmssp2_name *attrptr;
357+
const struct nls_table *nlsc = ses->local_nls;
358+
struct ntlmssp2_name *av;
359+
u16 len, nlen;
337360

338-
if (!ses->auth_key.len || !ses->auth_key.response)
361+
if (*name)
339362
return 0;
340363

341-
blobptr = ses->auth_key.response;
342-
blobend = blobptr + ses->auth_key.len;
343-
344-
while (blobptr + onesize < blobend) {
345-
attrptr = (struct ntlmssp2_name *) blobptr;
346-
type = le16_to_cpu(attrptr->type);
347-
if (type == NTLMSSP_AV_EOL)
348-
break;
349-
blobptr += 2; /* advance attr type */
350-
attrsize = le16_to_cpu(attrptr->length);
351-
blobptr += 2; /* advance attr size */
352-
if (blobptr + attrsize > blobend)
364+
av_for_each_entry(ses, av) {
365+
len = AV_LEN(av);
366+
if (AV_TYPE(av) != type)
367+
continue;
368+
if (!IS_ALIGNED(len, sizeof(__le16))) {
369+
cifs_dbg(VFS | ONCE, "%s: bad length(%u) for type %u\n",
370+
__func__, len, type);
371+
continue;
372+
}
373+
nlen = len / sizeof(__le16);
374+
if (nlen <= maxlen) {
375+
++nlen;
376+
*name = kmalloc(nlen, GFP_KERNEL);
377+
if (!*name)
378+
return -ENOMEM;
379+
cifs_from_utf16(*name, AV_DATA_PTR(av), nlen,
380+
len, nlsc, NO_MAP_UNI_RSVD);
353381
break;
354-
if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
355-
if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
356-
break;
357-
if (!ses->domainName) {
358-
ses->domainName =
359-
kmalloc(attrsize + 1, GFP_KERNEL);
360-
if (!ses->domainName)
361-
return -ENOMEM;
362-
cifs_from_utf16(ses->domainName,
363-
(__le16 *)blobptr, attrsize, attrsize,
364-
nls_cp, NO_MAP_UNI_RSVD);
365-
break;
366-
}
367382
}
368-
blobptr += attrsize; /* advance attr value */
369383
}
370-
371384
return 0;
372385
}
373386

@@ -377,40 +390,16 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
377390
* as part of ntlmv2 authentication (or local current time as
378391
* default in case of failure)
379392
*/
380-
static __le64
381-
find_timestamp(struct cifs_ses *ses)
393+
static __le64 find_timestamp(struct cifs_ses *ses)
382394
{
383-
unsigned int attrsize;
384-
unsigned int type;
385-
unsigned int onesize = sizeof(struct ntlmssp2_name);
386-
unsigned char *blobptr;
387-
unsigned char *blobend;
388-
struct ntlmssp2_name *attrptr;
395+
struct ntlmssp2_name *av;
389396
struct timespec64 ts;
390397

391-
if (!ses->auth_key.len || !ses->auth_key.response)
392-
return 0;
393-
394-
blobptr = ses->auth_key.response;
395-
blobend = blobptr + ses->auth_key.len;
396-
397-
while (blobptr + onesize < blobend) {
398-
attrptr = (struct ntlmssp2_name *) blobptr;
399-
type = le16_to_cpu(attrptr->type);
400-
if (type == NTLMSSP_AV_EOL)
401-
break;
402-
blobptr += 2; /* advance attr type */
403-
attrsize = le16_to_cpu(attrptr->length);
404-
blobptr += 2; /* advance attr size */
405-
if (blobptr + attrsize > blobend)
406-
break;
407-
if (type == NTLMSSP_AV_TIMESTAMP) {
408-
if (attrsize == sizeof(u64))
409-
return *((__le64 *)blobptr);
410-
}
411-
blobptr += attrsize; /* advance attr value */
398+
av_for_each_entry(ses, av) {
399+
if (AV_TYPE(av) == NTLMSSP_AV_TIMESTAMP &&
400+
AV_LEN(av) == sizeof(u64))
401+
return *((__le64 *)AV_DATA_PTR(av));
412402
}
413-
414403
ktime_get_real_ts64(&ts);
415404
return cpu_to_le64(cifs_UnixTimeToNT(ts));
416405
}
@@ -563,16 +552,29 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
563552
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
564553
if (!ses->domainName) {
565554
if (ses->domainAuto) {
566-
rc = find_domain_name(ses, nls_cp);
567-
if (rc) {
568-
cifs_dbg(VFS, "error %d finding domain name\n",
569-
rc);
555+
/*
556+
* Domain (workgroup) hasn't been specified in
557+
* mount options, so try to find it in
558+
* CHALLENGE_MESSAGE message and then use it as
559+
* part of NTLMv2 authentication.
560+
*/
561+
rc = find_av_name(ses, NTLMSSP_AV_NB_DOMAIN_NAME,
562+
&ses->domainName,
563+
CIFS_MAX_DOMAINNAME_LEN);
564+
if (rc)
570565
goto setup_ntlmv2_rsp_ret;
571-
}
572566
} else {
573567
ses->domainName = kstrdup("", GFP_KERNEL);
568+
if (!ses->domainName) {
569+
rc = -ENOMEM;
570+
goto setup_ntlmv2_rsp_ret;
571+
}
574572
}
575573
}
574+
rc = find_av_name(ses, NTLMSSP_AV_DNS_DOMAIN_NAME,
575+
&ses->dns_dom, CIFS_MAX_DOMAINNAME_LEN);
576+
if (rc)
577+
goto setup_ntlmv2_rsp_ret;
576578
} else {
577579
rc = build_avpair_blob(ses, nls_cp);
578580
if (rc) {

fs/smb/client/cifsglob.h

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -811,23 +811,15 @@ struct TCP_Server_Info {
811811
bool use_swn_dstaddr;
812812
struct sockaddr_storage swn_dstaddr;
813813
#endif
814-
struct mutex refpath_lock; /* protects leaf_fullpath */
815814
/*
816-
* leaf_fullpath: Canonical DFS referral path related to this
817-
* connection.
818-
* It is used in DFS cache refresher, reconnect and may
819-
* change due to nested DFS links.
820-
*
821-
* Protected by @refpath_lock and @srv_lock. The @refpath_lock is
822-
* mostly used for not requiring a copy of @leaf_fullpath when getting
823-
* cached or new DFS referrals (which might also sleep during I/O).
824-
* While @srv_lock is held for making string and NULL comparisons against
825-
* both fields as in mount(2) and cache refresh.
815+
* Canonical DFS referral path used in cifs_reconnect() for failover as
816+
* well as in DFS cache refresher.
826817
*
827818
* format: \\HOST\SHARE[\OPTIONAL PATH]
828819
*/
829820
char *leaf_fullpath;
830821
bool dfs_conn:1;
822+
char dns_dom[CIFS_MAX_DOMAINNAME_LEN + 1];
831823
};
832824

833825
static inline bool is_smb1(struct TCP_Server_Info *server)
@@ -1154,6 +1146,7 @@ struct cifs_ses {
11541146
/* ========= end: protected by chan_lock ======== */
11551147
struct cifs_ses *dfs_root_ses;
11561148
struct nls_table *local_nls;
1149+
char *dns_dom; /* FQDN of the domain */
11571150
};
11581151

11591152
static inline bool
@@ -2311,4 +2304,24 @@ static inline bool cifs_ses_exiting(struct cifs_ses *ses)
23112304
return ret;
23122305
}
23132306

2307+
static inline bool cifs_netbios_name(const char *name, size_t namelen)
2308+
{
2309+
bool ret = false;
2310+
size_t i;
2311+
2312+
if (namelen >= 1 && namelen <= RFC1001_NAME_LEN) {
2313+
for (i = 0; i < namelen; i++) {
2314+
const unsigned char c = name[i];
2315+
2316+
if (c == '\\' || c == '/' || c == ':' || c == '*' ||
2317+
c == '?' || c == '"' || c == '<' || c == '>' ||
2318+
c == '|' || c == '.')
2319+
return false;
2320+
if (!ret && isalpha(c))
2321+
ret = true;
2322+
}
2323+
}
2324+
return ret;
2325+
}
2326+
23142327
#endif /* _CIFS_GLOB_H */

fs/smb/client/cifspdu.h

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ typedef union smb_com_session_setup_andx {
649649
struct ntlmssp2_name {
650650
__le16 type;
651651
__le16 length;
652-
/* char name[length]; */
652+
__u8 data[];
653653
} __attribute__((packed));
654654

655655
struct ntlmv2_resp {
@@ -1484,22 +1484,6 @@ struct file_notify_information {
14841484
__u8 FileName[];
14851485
} __attribute__((packed));
14861486

1487-
/* For IO_REPARSE_TAG_SYMLINK */
1488-
struct reparse_symlink_data {
1489-
__le32 ReparseTag;
1490-
__le16 ReparseDataLength;
1491-
__u16 Reserved;
1492-
__le16 SubstituteNameOffset;
1493-
__le16 SubstituteNameLength;
1494-
__le16 PrintNameOffset;
1495-
__le16 PrintNameLength;
1496-
__le32 Flags;
1497-
char PathBuffer[];
1498-
} __attribute__((packed));
1499-
1500-
/* Flag above */
1501-
#define SYMLINK_FLAG_RELATIVE 0x00000001
1502-
15031487
/* For IO_REPARSE_TAG_NFS */
15041488
#define NFS_SPECFILE_LNK 0x00000000014B4E4C
15051489
#define NFS_SPECFILE_CHR 0x0000000000524843

fs/smb/client/cifsproto.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,9 +474,6 @@ extern int cifs_query_reparse_point(const unsigned int xid,
474474
const char *full_path,
475475
u32 *tag, struct kvec *rsp,
476476
int *rsp_buftype);
477-
extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
478-
__u16 fid, char **symlinkinfo,
479-
const struct nls_table *nls_codepage);
480477
extern int CIFSSMB_set_compression(const unsigned int xid,
481478
struct cifs_tcon *tcon, __u16 fid);
482479
extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
@@ -680,7 +677,7 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
680677
}
681678

682679
int match_target_ip(struct TCP_Server_Info *server,
683-
const char *share, size_t share_len,
680+
const char *host, size_t hostlen,
684681
bool *result);
685682
int cifs_inval_name_dfs_link_error(const unsigned int xid,
686683
struct cifs_tcon *tcon,

0 commit comments

Comments
 (0)