summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsproto.h3
-rw-r--r--fs/cifs/cifssmb.c36
-rw-r--r--fs/cifs/link.c22
3 files changed, 20 insertions, 41 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 4167716d32f2..7d54a5a4dd55 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -260,8 +260,7 @@ extern int CIFSUnixCreateSymLink(const int xid,
const struct nls_table *nls_codepage);
extern int CIFSSMBUnixQuerySymLink(const int xid,
struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- char *syminfo, const int buflen,
+ const unsigned char *searchName, char **syminfo,
const struct nls_table *nls_codepage);
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
struct cifsTconInfo *tcon,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f15848374cfa..dfb8e391d538 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2382,8 +2382,7 @@ winCreateHardLinkRetry:
int
CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- char *symlinkinfo, const int buflen,
+ const unsigned char *searchName, char **symlinkinfo,
const struct nls_table *nls_codepage)
{
/* SMB_QUERY_FILE_UNIX_LINK */
@@ -2393,6 +2392,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
__u16 params, byte_count;
+ char *data_start;
cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
@@ -2447,30 +2447,22 @@ querySymLinkRetry:
/* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc || (pSMBr->ByteCount < 2))
/* BB also check enough total bytes returned */
- rc = -EIO; /* bad smb */
+ if (rc || (pSMBr->ByteCount < 2))
+ rc = -EIO;
else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+
+ data_start = ((char *) &pSMBr->hdr.Protocol) +
+ le16_to_cpu(pSMBr->t2.DataOffset);
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = UniStrnlen((wchar_t *) ((char *)
- &pSMBr->hdr.Protocol + data_offset),
- min_t(const int, buflen, count) / 2);
/* BB FIXME investigate remapping reserved chars here */
- cifs_strfromUCS_le(symlinkinfo,
- (__le16 *) ((char *)&pSMBr->hdr.Protocol
- + data_offset),
- name_len, nls_codepage);
- } else {
- strncpy(symlinkinfo,
- (char *) &pSMBr->hdr.Protocol +
- data_offset,
- min_t(const int, buflen, count));
- }
- symlinkinfo[buflen] = 0;
- /* just in case so calling code does not go off the end of buffer */
+ *symlinkinfo = cifs_strndup(data_start, count,
+ pSMBr->hdr.Flags2 &
+ SMBFLG2_UNICODE,
+ nls_codepage);
+ if (!symlinkinfo)
+ rc = -ENOMEM;
}
}
cifs_buf_release(pSMB);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 63f644000ce5..e17a092f43ec 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -119,16 +119,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
full_path = build_path_from_dentry(direntry);
if (!full_path)
- goto out_no_free;
+ goto out;
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- target_path = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!target_path) {
- target_path = ERR_PTR(-ENOMEM);
- goto out;
- }
/* We could change this to:
if (pTcon->unix_ext)
@@ -138,8 +133,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
if (pTcon->ses->capabilities & CAP_UNIX)
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
- target_path,
- PATH_MAX-1,
+ &target_path,
cifs_sb->local_nls);
else {
/* BB add read reparse point symlink code here */
@@ -148,22 +142,16 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
/* BB Add MAC style xsymlink check here if enabled */
}
- if (rc == 0) {
-
-/* BB Add special case check for Samba DFS symlinks */
-
- target_path[PATH_MAX-1] = 0;
- } else {
+ if (rc != 0) {
kfree(target_path);
target_path = ERR_PTR(rc);
}
-out:
kfree(full_path);
-out_no_free:
+out:
FreeXid(xid);
nd_set_link(nd, target_path);
- return NULL; /* No cookie */
+ return NULL;
}
int
OpenPOWER on IntegriCloud