diff options
-rw-r--r-- | fs/cifs/cifsproto.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 21 | ||||
-rw-r--r-- | fs/cifs/inode.c | 5 |
3 files changed, 23 insertions, 4 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7dd2f48a4073..4a4fd2dbca63 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -119,6 +119,7 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, | |||
119 | extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 119 | extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, |
120 | const unsigned char *searchName, | 120 | const unsigned char *searchName, |
121 | FILE_ALL_INFO * findData, | 121 | FILE_ALL_INFO * findData, |
122 | int legacy /* whether to use old info level */, | ||
122 | const struct nls_table *nls_codepage, int remap); | 123 | const struct nls_table *nls_codepage, int remap); |
123 | extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | 124 | extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, |
124 | const unsigned char *searchName, | 125 | const unsigned char *searchName, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 79a01d35a783..6f50f2bc8870 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2969,6 +2969,7 @@ int | |||
2969 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2969 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, |
2970 | const unsigned char *searchName, | 2970 | const unsigned char *searchName, |
2971 | FILE_ALL_INFO * pFindData, | 2971 | FILE_ALL_INFO * pFindData, |
2972 | int legacy /* old style infolevel */, | ||
2972 | const struct nls_table *nls_codepage, int remap) | 2973 | const struct nls_table *nls_codepage, int remap) |
2973 | { | 2974 | { |
2974 | /* level 263 SMB_QUERY_FILE_ALL_INFO */ | 2975 | /* level 263 SMB_QUERY_FILE_ALL_INFO */ |
@@ -3017,7 +3018,10 @@ QPathInfoRetry: | |||
3017 | byte_count = params + 1 /* pad */ ; | 3018 | byte_count = params + 1 /* pad */ ; |
3018 | pSMB->TotalParameterCount = cpu_to_le16(params); | 3019 | pSMB->TotalParameterCount = cpu_to_le16(params); |
3019 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3020 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3020 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3021 | if(legacy) |
3022 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); | ||
3023 | else | ||
3024 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | ||
3021 | pSMB->Reserved4 = 0; | 3025 | pSMB->Reserved4 = 0; |
3022 | pSMB->hdr.smb_buf_length += byte_count; | 3026 | pSMB->hdr.smb_buf_length += byte_count; |
3023 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3027 | pSMB->ByteCount = cpu_to_le16(byte_count); |
@@ -3029,13 +3033,24 @@ QPathInfoRetry: | |||
3029 | } else { /* decode response */ | 3033 | } else { /* decode response */ |
3030 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3034 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3031 | 3035 | ||
3032 | if (rc || (pSMBr->ByteCount < 40)) | 3036 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
3037 | rc = -EIO; | ||
3038 | else if (!legacy && (pSMBr->ByteCount < 40)) | ||
3033 | rc = -EIO; /* bad smb */ | 3039 | rc = -EIO; /* bad smb */ |
3040 | else if(legacy && (pSMBr->ByteCount < 24)) | ||
3041 | rc = -EIO; /* 24 or 26 expected but we do not read last field */ | ||
3034 | else if (pFindData){ | 3042 | else if (pFindData){ |
3043 | int size; | ||
3035 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3044 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
3045 | if(legacy) /* we do not read the last field, EAsize, fortunately | ||
3046 | since it varies by subdialect and on Set vs. Get, is | ||
3047 | two bytes or 4 bytes depending but we don't care here */ | ||
3048 | size = sizeof(FILE_INFO_STANDARD); | ||
3049 | else | ||
3050 | size = sizeof(FILE_ALL_INFO); | ||
3036 | memcpy((char *) pFindData, | 3051 | memcpy((char *) pFindData, |
3037 | (char *) &pSMBr->hdr.Protocol + | 3052 | (char *) &pSMBr->hdr.Protocol + |
3038 | data_offset, sizeof (FILE_ALL_INFO)); | 3053 | data_offset, size); |
3039 | } else | 3054 | } else |
3040 | rc = -ENOMEM; | 3055 | rc = -ENOMEM; |
3041 | } | 3056 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 06dbce3a1815..fe6d21f99964 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -338,6 +338,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
338 | pfindData = (FILE_ALL_INFO *)buf; | 338 | pfindData = (FILE_ALL_INFO *)buf; |
339 | /* could do find first instead but this returns more info */ | 339 | /* could do find first instead but this returns more info */ |
340 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, | 340 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, |
341 | 0 /* not legacy */, | ||
341 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 342 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
342 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 343 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
343 | /* BB optimize code so we do not make the above call | 344 | /* BB optimize code so we do not make the above call |
@@ -385,8 +386,10 @@ int cifs_get_inode_info(struct inode **pinode, | |||
385 | /* get new inode */ | 386 | /* get new inode */ |
386 | if (*pinode == NULL) { | 387 | if (*pinode == NULL) { |
387 | *pinode = new_inode(sb); | 388 | *pinode = new_inode(sb); |
388 | if (*pinode == NULL) | 389 | if (*pinode == NULL) { |
390 | kfree(buf); | ||
389 | return -ENOMEM; | 391 | return -ENOMEM; |
392 | } | ||
390 | /* Is an i_ino of zero legal? Can we use that to check | 393 | /* Is an i_ino of zero legal? Can we use that to check |
391 | if the server supports returning inode numbers? Are | 394 | if the server supports returning inode numbers? Are |
392 | there other sanity checks we can use to ensure that | 395 | there other sanity checks we can use to ensure that |