aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-12 14:11:39 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-12 14:11:39 -0500
commit46015977e70f672ae6b20a1b5fb1e361208365ba (patch)
treee3be0785eff90cc8023cd1ea03fc22d3dcf37f41 /fs/cifs/cifssmb.c
parent92d140e21f1ce8cf99320afbbcad73879128e6dc (diff)
parent9b8f5f573770f33b28c45255ac82e6457278c782 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (21 commits) [CIFS] fix oops on second mount to same server when null auth is used [CIFS] Fix stale mode after readdir when cifsacl specified [CIFS] add mode to acl conversion helper function [CIFS] Fix incorrect mode when ACL had deny access control entries [CIFS] Add uid to key description so krb can handle user mounts [CIFS] Fix walking out end of cifs dacl [CIFS] Add upcall files for cifs to use spnego/kerberos [CIFS] add OIDs for KRB5 and MSKRB5 to ASN1 parsing routines [CIFS] Register and unregister cifs_spnego_key_type on module init/exit [CIFS] implement upcalls for SPNEGO blob via keyctl API [CIFS] allow cifs_calc_signature2 to deal with a zero length iovec [CIFS] If no Access Control Entries, set mode perm bits to zero [CIFS] when mount helper missing fix slash wrong direction in share [CIFS] Don't request too much permission when reading an ACL [CIFS] enable get mode from ACL when cifsacl mount option specified [CIFS] ACL support part 8 [CIFS] acl support part 7 [CIFS] acl support part 6 [CIFS] acl support part 6 [CIFS] remove unused funtion compile warning when experimental off ...
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f0d9a485d095..59d7b7c037ad 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -647,8 +647,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
647 count - 16, 647 count - 16,
648 &server->secType); 648 &server->secType);
649 if (rc == 1) { 649 if (rc == 1) {
650 /* BB Need to fill struct for sessetup here */ 650 rc = 0;
651 rc = -EOPNOTSUPP;
652 } else { 651 } else {
653 rc = -EINVAL; 652 rc = -EINVAL;
654 } 653 }
@@ -2486,6 +2485,7 @@ querySymLinkRetry:
2486 return rc; 2485 return rc;
2487} 2486}
2488 2487
2488#ifdef CONFIG_CIFS_EXPERIMENTAL
2489/* Initialize NT TRANSACT SMB into small smb request buffer. 2489/* Initialize NT TRANSACT SMB into small smb request buffer.
2490 This assumes that all NT TRANSACTS that we init here have 2490 This assumes that all NT TRANSACTS that we init here have
2491 total parm and data under about 400 bytes (to fit in small cifs 2491 total parm and data under about 400 bytes (to fit in small cifs
@@ -2494,7 +2494,7 @@ querySymLinkRetry:
2494 MaxSetupCount (size of returned setup area) and 2494 MaxSetupCount (size of returned setup area) and
2495 MaxParameterCount (returned parms size) must be set by caller */ 2495 MaxParameterCount (returned parms size) must be set by caller */
2496static int 2496static int
2497smb_init_ntransact(const __u16 sub_command, const int setup_count, 2497smb_init_nttransact(const __u16 sub_command, const int setup_count,
2498 const int parm_len, struct cifsTconInfo *tcon, 2498 const int parm_len, struct cifsTconInfo *tcon,
2499 void **ret_buf) 2499 void **ret_buf)
2500{ 2500{
@@ -2525,12 +2525,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count,
2525 2525
2526static int 2526static int
2527validate_ntransact(char *buf, char **ppparm, char **ppdata, 2527validate_ntransact(char *buf, char **ppparm, char **ppdata,
2528 int *pdatalen, int *pparmlen) 2528 __u32 *pparmlen, __u32 *pdatalen)
2529{ 2529{
2530 char *end_of_smb; 2530 char *end_of_smb;
2531 __u32 data_count, data_offset, parm_count, parm_offset; 2531 __u32 data_count, data_offset, parm_count, parm_offset;
2532 struct smb_com_ntransact_rsp *pSMBr; 2532 struct smb_com_ntransact_rsp *pSMBr;
2533 2533
2534 *pdatalen = 0;
2535 *pparmlen = 0;
2536
2534 if (buf == NULL) 2537 if (buf == NULL)
2535 return -EINVAL; 2538 return -EINVAL;
2536 2539
@@ -2567,8 +2570,11 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
2567 cFYI(1, ("parm count and data count larger than SMB")); 2570 cFYI(1, ("parm count and data count larger than SMB"));
2568 return -EINVAL; 2571 return -EINVAL;
2569 } 2572 }
2573 *pdatalen = data_count;
2574 *pparmlen = parm_count;
2570 return 0; 2575 return 0;
2571} 2576}
2577#endif /* CIFS_EXPERIMENTAL */
2572 2578
2573int 2579int
2574CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, 2580CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3067,8 +3073,7 @@ GetExtAttrOut:
3067/* Get Security Descriptor (by handle) from remote server for a file or dir */ 3073/* Get Security Descriptor (by handle) from remote server for a file or dir */
3068int 3074int
3069CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, 3075CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3070 /* BB fix up return info */ char *acl_inf, const int buflen, 3076 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3071 const int acl_type)
3072{ 3077{
3073 int rc = 0; 3078 int rc = 0;
3074 int buf_type = 0; 3079 int buf_type = 0;
@@ -3077,7 +3082,10 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3077 3082
3078 cFYI(1, ("GetCifsACL")); 3083 cFYI(1, ("GetCifsACL"));
3079 3084
3080 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, 3085 *pbuflen = 0;
3086 *acl_inf = NULL;
3087
3088 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3081 8 /* parm len */, tcon, (void **) &pSMB); 3089 8 /* parm len */, tcon, (void **) &pSMB);
3082 if (rc) 3090 if (rc)
3083 return rc; 3091 return rc;
@@ -3099,34 +3107,52 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3099 if (rc) { 3107 if (rc) {
3100 cFYI(1, ("Send error in QuerySecDesc = %d", rc)); 3108 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3101 } else { /* decode response */ 3109 } else { /* decode response */
3102 struct cifs_ntsd *psec_desc;
3103 __le32 * parm; 3110 __le32 * parm;
3104 int parm_len; 3111 __u32 parm_len;
3105 int data_len; 3112 __u32 acl_len;
3106 int acl_len;
3107 struct smb_com_ntransact_rsp *pSMBr; 3113 struct smb_com_ntransact_rsp *pSMBr;
3114 char *pdata;
3108 3115
3109/* validate_nttransact */ 3116/* validate_nttransact */
3110 rc = validate_ntransact(iov[0].iov_base, (char **)&parm, 3117 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3111 (char **)&psec_desc, 3118 &pdata, &parm_len, pbuflen);
3112 &parm_len, &data_len);
3113 if (rc) 3119 if (rc)
3114 goto qsec_out; 3120 goto qsec_out;
3115 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; 3121 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3116 3122
3117 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc)); 3123 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3118 3124
3119 if (le32_to_cpu(pSMBr->ParameterCount) != 4) { 3125 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3120 rc = -EIO; /* bad smb */ 3126 rc = -EIO; /* bad smb */
3127 *pbuflen = 0;
3121 goto qsec_out; 3128 goto qsec_out;
3122 } 3129 }
3123 3130
3124/* BB check that data area is minimum length and as big as acl_len */ 3131/* BB check that data area is minimum length and as big as acl_len */
3125 3132
3126 acl_len = le32_to_cpu(*parm); 3133 acl_len = le32_to_cpu(*parm);
3127 /* BB check if (acl_len > bufsize) */ 3134 if (acl_len != *pbuflen) {
3135 cERROR(1, ("acl length %d does not match %d",
3136 acl_len, *pbuflen));
3137 if (*pbuflen > acl_len)
3138 *pbuflen = acl_len;
3139 }
3128 3140
3129 parse_sec_desc(psec_desc, acl_len); 3141 /* check if buffer is big enough for the acl
3142 header followed by the smallest SID */
3143 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3144 (*pbuflen >= 64 * 1024)) {
3145 cERROR(1, ("bad acl length %d", *pbuflen));
3146 rc = -EINVAL;
3147 *pbuflen = 0;
3148 } else {
3149 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3150 if (*acl_inf == NULL) {
3151 *pbuflen = 0;
3152 rc = -ENOMEM;
3153 }
3154 memcpy(*acl_inf, pdata, *pbuflen);
3155 }
3130 } 3156 }
3131qsec_out: 3157qsec_out:
3132 if (buf_type == CIFS_SMALL_BUFFER) 3158 if (buf_type == CIFS_SMALL_BUFFER)
@@ -3381,7 +3407,7 @@ UnixQPathInfoRetry:
3381 memcpy((char *) pFindData, 3407 memcpy((char *) pFindData,
3382 (char *) &pSMBr->hdr.Protocol + 3408 (char *) &pSMBr->hdr.Protocol +
3383 data_offset, 3409 data_offset,
3384 sizeof (FILE_UNIX_BASIC_INFO)); 3410 sizeof(FILE_UNIX_BASIC_INFO));
3385 } 3411 }
3386 } 3412 }
3387 cifs_buf_release(pSMB); 3413 cifs_buf_release(pSMB);
@@ -3649,7 +3675,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3649 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); 3675 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3650 pSMB->SearchHandle = searchHandle; /* always kept as le */ 3676 pSMB->SearchHandle = searchHandle; /* always kept as le */
3651 pSMB->SearchCount = 3677 pSMB->SearchCount =
3652 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO)); 3678 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3653 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); 3679 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3654 pSMB->ResumeKey = psrch_inf->resume_key; 3680 pSMB->ResumeKey = psrch_inf->resume_key;
3655 pSMB->SearchFlags = 3681 pSMB->SearchFlags =
@@ -4331,7 +4357,7 @@ QFSDeviceRetry:
4331 } else { /* decode response */ 4357 } else { /* decode response */
4332 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 4358 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4333 4359
4334 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))) 4360 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4335 rc = -EIO; /* bad smb */ 4361 rc = -EIO; /* bad smb */
4336 else { 4362 else {
4337 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 4363 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);