aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 61d24f6ee64e..cc17e98991f3 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2526,12 +2526,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count,
2526 2526
2527static int 2527static int
2528validate_ntransact(char *buf, char **ppparm, char **ppdata, 2528validate_ntransact(char *buf, char **ppparm, char **ppdata,
2529 int *pdatalen, int *pparmlen) 2529 __u32 *pdatalen, __u32 *pparmlen)
2530{ 2530{
2531 char *end_of_smb; 2531 char *end_of_smb;
2532 __u32 data_count, data_offset, parm_count, parm_offset; 2532 __u32 data_count, data_offset, parm_count, parm_offset;
2533 struct smb_com_ntransact_rsp *pSMBr; 2533 struct smb_com_ntransact_rsp *pSMBr;
2534 2534
2535 *pdatalen = 0;
2536 *pparmlen = 0;
2537
2535 if (buf == NULL) 2538 if (buf == NULL)
2536 return -EINVAL; 2539 return -EINVAL;
2537 2540
@@ -2568,6 +2571,8 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
2568 cFYI(1, ("parm count and data count larger than SMB")); 2571 cFYI(1, ("parm count and data count larger than SMB"));
2569 return -EINVAL; 2572 return -EINVAL;
2570 } 2573 }
2574 *pdatalen = data_count;
2575 *pparmlen = parm_count;
2571 return 0; 2576 return 0;
2572} 2577}
2573#endif /* CIFS_EXPERIMENTAL */ 2578#endif /* CIFS_EXPERIMENTAL */
@@ -3069,8 +3074,7 @@ GetExtAttrOut:
3069/* Get Security Descriptor (by handle) from remote server for a file or dir */ 3074/* Get Security Descriptor (by handle) from remote server for a file or dir */
3070int 3075int
3071CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, 3076CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3072 /* BB fix up return info */ char *acl_inf, const int buflen, 3077 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3073 const int acl_type)
3074{ 3078{
3075 int rc = 0; 3079 int rc = 0;
3076 int buf_type = 0; 3080 int buf_type = 0;
@@ -3079,6 +3083,9 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3079 3083
3080 cFYI(1, ("GetCifsACL")); 3084 cFYI(1, ("GetCifsACL"));
3081 3085
3086 *pbuflen = 0;
3087 *acl_inf = NULL;
3088
3082 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, 3089 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3083 8 /* parm len */, tcon, (void **) &pSMB); 3090 8 /* parm len */, tcon, (void **) &pSMB);
3084 if (rc) 3091 if (rc)
@@ -3101,34 +3108,52 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3101 if (rc) { 3108 if (rc) {
3102 cFYI(1, ("Send error in QuerySecDesc = %d", rc)); 3109 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3103 } else { /* decode response */ 3110 } else { /* decode response */
3104 struct cifs_ntsd *psec_desc;
3105 __le32 * parm; 3111 __le32 * parm;
3106 int parm_len; 3112 __u32 parm_len;
3107 int data_len; 3113 __u32 acl_len;
3108 int acl_len;
3109 struct smb_com_ntransact_rsp *pSMBr; 3114 struct smb_com_ntransact_rsp *pSMBr;
3115 char *pdata;
3110 3116
3111/* validate_nttransact */ 3117/* validate_nttransact */
3112 rc = validate_ntransact(iov[0].iov_base, (char **)&parm, 3118 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3113 (char **)&psec_desc, 3119 &pdata, &parm_len, pbuflen);
3114 &parm_len, &data_len);
3115 if (rc) 3120 if (rc)
3116 goto qsec_out; 3121 goto qsec_out;
3117 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; 3122 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3118 3123
3119 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc)); 3124 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3120 3125
3121 if (le32_to_cpu(pSMBr->ParameterCount) != 4) { 3126 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3122 rc = -EIO; /* bad smb */ 3127 rc = -EIO; /* bad smb */
3128 *pbuflen = 0;
3123 goto qsec_out; 3129 goto qsec_out;
3124 } 3130 }
3125 3131
3126/* BB check that data area is minimum length and as big as acl_len */ 3132/* BB check that data area is minimum length and as big as acl_len */
3127 3133
3128 acl_len = le32_to_cpu(*parm); 3134 acl_len = le32_to_cpu(*parm);
3129 /* BB check if (acl_len > bufsize) */ 3135 if (acl_len != *pbuflen) {
3136 cERROR(1, ("acl length %d does not match %d",
3137 acl_len, *pbuflen));
3138 if (*pbuflen > acl_len)
3139 *pbuflen = acl_len;
3140 }
3130 3141
3131 parse_sec_desc(psec_desc, acl_len); 3142 /* check if buffer is big enough for the acl
3143 header followed by the smallest SID */
3144 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3145 (*pbuflen >= 64 * 1024)) {
3146 cERROR(1, ("bad acl length %d", *pbuflen));
3147 rc = -EINVAL;
3148 *pbuflen = 0;
3149 } else {
3150 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3151 if (*acl_inf == NULL) {
3152 *pbuflen = 0;
3153 rc = -ENOMEM;
3154 }
3155 memcpy(*acl_inf, pdata, *pbuflen);
3156 }
3132 } 3157 }
3133qsec_out: 3158qsec_out:
3134 if (buf_type == CIFS_SMALL_BUFFER) 3159 if (buf_type == CIFS_SMALL_BUFFER)
@@ -3383,7 +3408,7 @@ UnixQPathInfoRetry:
3383 memcpy((char *) pFindData, 3408 memcpy((char *) pFindData,
3384 (char *) &pSMBr->hdr.Protocol + 3409 (char *) &pSMBr->hdr.Protocol +
3385 data_offset, 3410 data_offset,
3386 sizeof (FILE_UNIX_BASIC_INFO)); 3411 sizeof(FILE_UNIX_BASIC_INFO));
3387 } 3412 }
3388 } 3413 }
3389 cifs_buf_release(pSMB); 3414 cifs_buf_release(pSMB);
@@ -3651,7 +3676,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3651 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); 3676 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3652 pSMB->SearchHandle = searchHandle; /* always kept as le */ 3677 pSMB->SearchHandle = searchHandle; /* always kept as le */
3653 pSMB->SearchCount = 3678 pSMB->SearchCount =
3654 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO)); 3679 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3655 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); 3680 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3656 pSMB->ResumeKey = psrch_inf->resume_key; 3681 pSMB->ResumeKey = psrch_inf->resume_key;
3657 pSMB->SearchFlags = 3682 pSMB->SearchFlags =
@@ -4333,7 +4358,7 @@ QFSDeviceRetry:
4333 } else { /* decode response */ 4358 } else { /* decode response */
4334 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 4359 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4335 4360
4336 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))) 4361 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4337 rc = -EIO; /* bad smb */ 4362 rc = -EIO; /* bad smb */
4338 else { 4363 else {
4339 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 4364 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);