diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 55 |
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 | ||
2527 | static int | 2527 | static int |
2528 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | 2528 | validate_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 */ |
3070 | int | 3075 | int |
3071 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3076 | CIFSSMBGetCIFSACL(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 | } |
3133 | qsec_out: | 3158 | qsec_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); |