diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-12 14:11:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-12 14:11:39 -0500 |
commit | 46015977e70f672ae6b20a1b5fb1e361208365ba (patch) | |
tree | e3be0785eff90cc8023cd1ea03fc22d3dcf37f41 /fs/cifs/cifssmb.c | |
parent | 92d140e21f1ce8cf99320afbbcad73879128e6dc (diff) | |
parent | 9b8f5f573770f33b28c45255ac82e6457278c782 (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.c | 64 |
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 */ |
2496 | static int | 2496 | static int |
2497 | smb_init_ntransact(const __u16 sub_command, const int setup_count, | 2497 | smb_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 | ||
2526 | static int | 2526 | static int |
2527 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | 2527 | validate_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 | ||
2573 | int | 2579 | int |
2574 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2580 | CIFSSMBQueryReparseLinkInfo(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 */ |
3068 | int | 3074 | int |
3069 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3075 | CIFSSMBGetCIFSACL(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 | } |
3131 | qsec_out: | 3157 | qsec_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); |