diff options
author | Steve French <sfrench@us.ibm.com> | 2007-12-31 02:47:21 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2007-12-31 02:47:21 -0500 |
commit | 97837582bc1e191d2792af74c1f3762ed01243b9 (patch) | |
tree | c472591913d02cc4fb107815c53221044fdc9a6c | |
parent | 28c5a02a11f70bb1fd8dd3b633206e2db3220308 (diff) |
[CIFS] Allow setting mode via cifs acl
Requires cifsacl mount flag to be on and CIFS_EXPERIMENTAL enabled
CC: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/CHANGES | 2 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 240 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 65 | ||||
-rw-r--r-- | fs/cifs/inode.c | 14 |
6 files changed, 315 insertions, 13 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 0c778765bd79..edd248367b36 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -5,6 +5,8 @@ Enable experimental Kerberos support. Return writebehind errors on flush | |||
5 | and sync so that events like out of disk space get reported properly on | 5 | and sync so that events like out of disk space get reported properly on |
6 | cached files. Fix setxattr failure to certain Samba versions. Fix mount | 6 | cached files. Fix setxattr failure to certain Samba versions. Fix mount |
7 | of second share to disconnected server session (autoreconnect on this). | 7 | of second share to disconnected server session (autoreconnect on this). |
8 | Add ability to modify cifs acls for handling chmod (when mounted with | ||
9 | cifsacl flag). | ||
8 | 10 | ||
9 | Version 1.51 | 11 | Version 1.51 |
10 | ------------ | 12 | ------------ |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c312adcba4fc..a7035bd18e4e 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -129,6 +129,54 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
129 | return (1); /* sids compare/match */ | 129 | return (1); /* sids compare/match */ |
130 | } | 130 | } |
131 | 131 | ||
132 | |||
133 | /* copy ntsd, owner sid, and group sid from a security descriptor to another */ | ||
134 | static void copy_sec_desc(const struct cifs_ntsd *pntsd, | ||
135 | struct cifs_ntsd *pnntsd, __u32 sidsoffset) | ||
136 | { | ||
137 | int i; | ||
138 | |||
139 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | ||
140 | struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; | ||
141 | |||
142 | /* copy security descriptor control portion */ | ||
143 | pnntsd->revision = pntsd->revision; | ||
144 | pnntsd->type = pntsd->type; | ||
145 | pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd)); | ||
146 | pnntsd->sacloffset = 0; | ||
147 | pnntsd->osidoffset = cpu_to_le32(sidsoffset); | ||
148 | pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid)); | ||
149 | |||
150 | /* copy owner sid */ | ||
151 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | ||
152 | le32_to_cpu(pntsd->osidoffset)); | ||
153 | nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); | ||
154 | |||
155 | nowner_sid_ptr->revision = owner_sid_ptr->revision; | ||
156 | nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; | ||
157 | for (i = 0; i < 6; i++) | ||
158 | nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; | ||
159 | for (i = 0; i < 5; i++) | ||
160 | nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; | ||
161 | |||
162 | /* copy group sid */ | ||
163 | group_sid_ptr = (struct cifs_sid *)((char *)pntsd + | ||
164 | le32_to_cpu(pntsd->gsidoffset)); | ||
165 | ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + | ||
166 | sizeof(struct cifs_sid)); | ||
167 | |||
168 | ngroup_sid_ptr->revision = group_sid_ptr->revision; | ||
169 | ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; | ||
170 | for (i = 0; i < 6; i++) | ||
171 | ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; | ||
172 | for (i = 0; i < 5; i++) | ||
173 | ngroup_sid_ptr->sub_auth[i] = | ||
174 | cpu_to_le32(group_sid_ptr->sub_auth[i]); | ||
175 | |||
176 | return; | ||
177 | } | ||
178 | |||
179 | |||
132 | /* | 180 | /* |
133 | change posix mode to reflect permissions | 181 | change posix mode to reflect permissions |
134 | pmode is the existing mode (we only want to overwrite part of this | 182 | pmode is the existing mode (we only want to overwrite part of this |
@@ -220,6 +268,33 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, | |||
220 | return; | 268 | return; |
221 | } | 269 | } |
222 | 270 | ||
271 | static __le16 fill_ace_for_sid(struct cifs_ace *pntace, | ||
272 | const struct cifs_sid *psid, __u64 nmode, umode_t bits) | ||
273 | { | ||
274 | int i; | ||
275 | __u16 size = 0; | ||
276 | __u32 access_req = 0; | ||
277 | |||
278 | pntace->type = ACCESS_ALLOWED; | ||
279 | pntace->flags = 0x0; | ||
280 | mode_to_access_flags(nmode, bits, &access_req); | ||
281 | if (!access_req) | ||
282 | access_req = SET_MINIMUM_RIGHTS; | ||
283 | pntace->access_req = cpu_to_le32(access_req); | ||
284 | |||
285 | pntace->sid.revision = psid->revision; | ||
286 | pntace->sid.num_subauth = psid->num_subauth; | ||
287 | for (i = 0; i < 6; i++) | ||
288 | pntace->sid.authority[i] = psid->authority[i]; | ||
289 | for (i = 0; i < psid->num_subauth; i++) | ||
290 | pntace->sid.sub_auth[i] = psid->sub_auth[i]; | ||
291 | |||
292 | size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4); | ||
293 | pntace->size = cpu_to_le16(size); | ||
294 | |||
295 | return (size); | ||
296 | } | ||
297 | |||
223 | 298 | ||
224 | #ifdef CONFIG_CIFS_DEBUG2 | 299 | #ifdef CONFIG_CIFS_DEBUG2 |
225 | static void dump_ace(struct cifs_ace *pace, char *end_of_acl) | 300 | static void dump_ace(struct cifs_ace *pace, char *end_of_acl) |
@@ -243,7 +318,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) | |||
243 | int i; | 318 | int i; |
244 | cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d", | 319 | cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d", |
245 | pace->sid.revision, pace->sid.num_subauth, pace->type, | 320 | pace->sid.revision, pace->sid.num_subauth, pace->type, |
246 | pace->flags, pace->size)); | 321 | pace->flags, le16_to_cpu(pace->size))); |
247 | for (i = 0; i < num_subauth; ++i) { | 322 | for (i = 0; i < num_subauth; ++i) { |
248 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, | 323 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, |
249 | le32_to_cpu(pace->sid.sub_auth[i]))); | 324 | le32_to_cpu(pace->sid.sub_auth[i]))); |
@@ -346,6 +421,28 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
346 | } | 421 | } |
347 | 422 | ||
348 | 423 | ||
424 | static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, | ||
425 | struct cifs_sid *pgrpsid, __u64 nmode) | ||
426 | { | ||
427 | __le16 size = 0; | ||
428 | struct cifs_acl *pnndacl; | ||
429 | |||
430 | pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl)); | ||
431 | |||
432 | size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size), | ||
433 | pownersid, nmode, S_IRWXU); | ||
434 | size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), | ||
435 | pgrpsid, nmode, S_IRWXG); | ||
436 | size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), | ||
437 | &sid_everyone, nmode, S_IRWXO); | ||
438 | |||
439 | pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl)); | ||
440 | pndacl->num_aces = 3; | ||
441 | |||
442 | return (0); | ||
443 | } | ||
444 | |||
445 | |||
349 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | 446 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) |
350 | { | 447 | { |
351 | /* BB need to add parm so we can store the SID BB */ | 448 | /* BB need to add parm so we can store the SID BB */ |
@@ -432,6 +529,46 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
432 | } | 529 | } |
433 | 530 | ||
434 | 531 | ||
532 | /* Convert permission bits from mode to equivalent CIFS ACL */ | ||
533 | static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, | ||
534 | int acl_len, struct inode *inode, __u64 nmode) | ||
535 | { | ||
536 | int rc = 0; | ||
537 | __u32 dacloffset; | ||
538 | __u32 ndacloffset; | ||
539 | __u32 sidsoffset; | ||
540 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | ||
541 | struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */ | ||
542 | struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */ | ||
543 | |||
544 | if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL)) | ||
545 | return (-EIO); | ||
546 | |||
547 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | ||
548 | le32_to_cpu(pntsd->osidoffset)); | ||
549 | group_sid_ptr = (struct cifs_sid *)((char *)pntsd + | ||
550 | le32_to_cpu(pntsd->gsidoffset)); | ||
551 | |||
552 | dacloffset = le32_to_cpu(pntsd->dacloffset); | ||
553 | dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); | ||
554 | |||
555 | ndacloffset = sizeof(struct cifs_ntsd); | ||
556 | ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset); | ||
557 | ndacl_ptr->revision = dacl_ptr->revision; | ||
558 | ndacl_ptr->size = 0; | ||
559 | ndacl_ptr->num_aces = 0; | ||
560 | |||
561 | rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode); | ||
562 | |||
563 | sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); | ||
564 | |||
565 | /* copy security descriptor control portion and owner and group sid */ | ||
566 | copy_sec_desc(pntsd, pnntsd, sidsoffset); | ||
567 | |||
568 | return (rc); | ||
569 | } | ||
570 | |||
571 | |||
435 | /* Retrieve an ACL from the server */ | 572 | /* Retrieve an ACL from the server */ |
436 | static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | 573 | static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, |
437 | const char *path) | 574 | const char *path) |
@@ -487,6 +624,64 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | |||
487 | return pntsd; | 624 | return pntsd; |
488 | } | 625 | } |
489 | 626 | ||
627 | /* Set an ACL on the server */ | ||
628 | static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | ||
629 | struct inode *inode, const char *path) | ||
630 | { | ||
631 | struct cifsFileInfo *open_file; | ||
632 | int unlock_file = FALSE; | ||
633 | int xid; | ||
634 | int rc = -EIO; | ||
635 | __u16 fid; | ||
636 | struct super_block *sb; | ||
637 | struct cifs_sb_info *cifs_sb; | ||
638 | |||
639 | #ifdef CONFIG_CIFS_DEBUG2 | ||
640 | cFYI(1, ("set ACL for %s from mode 0x%x", path, inode->i_mode)); | ||
641 | #endif | ||
642 | |||
643 | if (!inode) | ||
644 | return (rc); | ||
645 | |||
646 | sb = inode->i_sb; | ||
647 | if (sb == NULL) | ||
648 | return (rc); | ||
649 | |||
650 | cifs_sb = CIFS_SB(sb); | ||
651 | xid = GetXid(); | ||
652 | |||
653 | open_file = find_readable_file(CIFS_I(inode)); | ||
654 | if (open_file) { | ||
655 | unlock_file = TRUE; | ||
656 | fid = open_file->netfid; | ||
657 | } else { | ||
658 | int oplock = FALSE; | ||
659 | /* open file */ | ||
660 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, | ||
661 | WRITE_DAC, 0, &fid, &oplock, NULL, | ||
662 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
663 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
664 | if (rc != 0) { | ||
665 | cERROR(1, ("Unable to open file to set ACL")); | ||
666 | FreeXid(xid); | ||
667 | return (rc); | ||
668 | } | ||
669 | } | ||
670 | |||
671 | rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); | ||
672 | #ifdef CONFIG_CIFS_DEBUG2 | ||
673 | cFYI(1, ("SetCIFSACL rc = %d", rc)); | ||
674 | #endif | ||
675 | if (unlock_file == TRUE) | ||
676 | atomic_dec(&open_file->wrtPending); | ||
677 | else | ||
678 | CIFSSMBClose(xid, cifs_sb->tcon, fid); | ||
679 | |||
680 | FreeXid(xid); | ||
681 | |||
682 | return (rc); | ||
683 | } | ||
684 | |||
490 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 685 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
491 | void acl_to_uid_mode(struct inode *inode, const char *path) | 686 | void acl_to_uid_mode(struct inode *inode, const char *path) |
492 | { | 687 | { |
@@ -510,24 +705,53 @@ void acl_to_uid_mode(struct inode *inode, const char *path) | |||
510 | } | 705 | } |
511 | 706 | ||
512 | /* Convert mode bits to an ACL so we can update the ACL on the server */ | 707 | /* Convert mode bits to an ACL so we can update the ACL on the server */ |
513 | int mode_to_acl(struct inode *inode, const char *path) | 708 | int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) |
514 | { | 709 | { |
515 | int rc = 0; | 710 | int rc = 0; |
516 | __u32 acllen = 0; | 711 | __u32 acllen = 0; |
517 | struct cifs_ntsd *pntsd = NULL; | 712 | struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ |
713 | struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ | ||
518 | 714 | ||
715 | #ifdef CONFIG_CIFS_DEBUG2 | ||
519 | cFYI(1, ("set ACL from mode for %s", path)); | 716 | cFYI(1, ("set ACL from mode for %s", path)); |
717 | #endif | ||
520 | 718 | ||
521 | /* Get the security descriptor */ | 719 | /* Get the security descriptor */ |
522 | pntsd = get_cifs_acl(&acllen, inode, path); | 720 | pntsd = get_cifs_acl(&acllen, inode, path); |
523 | 721 | ||
524 | /* Add/Modify the three ACEs for owner, group, everyone | 722 | /* Add three ACEs for owner, group, everyone getting rid of |
525 | while retaining the other ACEs */ | 723 | other ACEs as chmod disables ACEs and set the security descriptor */ |
526 | 724 | ||
527 | /* Set the security descriptor */ | 725 | if (pntsd) { |
726 | /* allocate memory for the smb header, | ||
727 | set security descriptor request security descriptor | ||
728 | parameters, and secuirty descriptor itself */ | ||
528 | 729 | ||
730 | pnntsd = kmalloc(acllen, GFP_KERNEL); | ||
731 | if (!pnntsd) { | ||
732 | cERROR(1, ("Unable to allocate security descriptor")); | ||
733 | kfree(pntsd); | ||
734 | return (-ENOMEM); | ||
735 | } | ||
529 | 736 | ||
530 | kfree(pntsd); | 737 | rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode); |
531 | return rc; | 738 | |
739 | #ifdef CONFIG_CIFS_DEBUG2 | ||
740 | cFYI(1, ("build_sec_desc rc: %d", rc)); | ||
741 | #endif | ||
742 | |||
743 | if (!rc) { | ||
744 | /* Set the security descriptor */ | ||
745 | rc = set_cifs_acl(pnntsd, acllen, inode, path); | ||
746 | #ifdef CONFIG_CIFS_DEBUG2 | ||
747 | cFYI(1, ("set_cifs_acl rc: %d", rc)); | ||
748 | #endif | ||
749 | } | ||
750 | |||
751 | kfree(pnntsd); | ||
752 | kfree(pntsd); | ||
753 | } | ||
754 | |||
755 | return (rc); | ||
532 | } | 756 | } |
533 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 757 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index dbe6b846f37f..47f79504f57b 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -237,6 +237,9 @@ | |||
237 | | DELETE | READ_CONTROL | WRITE_DAC \ | 237 | | DELETE | READ_CONTROL | WRITE_DAC \ |
238 | | WRITE_OWNER | SYNCHRONIZE) | 238 | | WRITE_OWNER | SYNCHRONIZE) |
239 | 239 | ||
240 | #define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \ | ||
241 | | READ_CONTROL | SYNCHRONIZE) | ||
242 | |||
240 | 243 | ||
241 | /* | 244 | /* |
242 | * Invalid readdir handle | 245 | * Invalid readdir handle |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 8350eec49663..7093cb4b0212 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -97,7 +97,7 @@ extern int cifs_get_inode_info_unix(struct inode **pinode, | |||
97 | const unsigned char *search_path, | 97 | const unsigned char *search_path, |
98 | struct super_block *sb, int xid); | 98 | struct super_block *sb, int xid); |
99 | extern void acl_to_uid_mode(struct inode *inode, const char *search_path); | 99 | extern void acl_to_uid_mode(struct inode *inode, const char *search_path); |
100 | extern int mode_to_acl(struct inode *inode, const char *path); | 100 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); |
101 | 101 | ||
102 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 102 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
103 | const char *); | 103 | const char *); |
@@ -342,6 +342,8 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, | |||
342 | const struct nls_table *nls_codepage, int remap_special_chars); | 342 | const struct nls_table *nls_codepage, int remap_special_chars); |
343 | extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, | 343 | extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, |
344 | __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); | 344 | __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); |
345 | extern int CIFSSMBSetCIFSACL(const int, struct cifsTconInfo *, __u16, | ||
346 | struct cifs_ntsd *, __u32); | ||
345 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 347 | extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, |
346 | const unsigned char *searchName, | 348 | const unsigned char *searchName, |
347 | char *acl_inf, const int buflen, const int acl_type, | 349 | char *acl_inf, const int buflen, const int acl_type, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 618542b8ce0b..9409524e4bf8 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -3156,6 +3156,71 @@ qsec_out: | |||
3156 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ | 3156 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ |
3157 | return rc; | 3157 | return rc; |
3158 | } | 3158 | } |
3159 | |||
3160 | int | ||
3161 | CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | ||
3162 | struct cifs_ntsd *pntsd, __u32 acllen) | ||
3163 | { | ||
3164 | __u16 byte_count, param_count, data_count, param_offset, data_offset; | ||
3165 | int rc = 0; | ||
3166 | int bytes_returned = 0; | ||
3167 | SET_SEC_DESC_REQ *pSMB = NULL; | ||
3168 | NTRANSACT_RSP *pSMBr = NULL; | ||
3169 | |||
3170 | setCifsAclRetry: | ||
3171 | rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, | ||
3172 | (void **) &pSMBr); | ||
3173 | if (rc) | ||
3174 | return (rc); | ||
3175 | |||
3176 | pSMB->MaxSetupCount = 0; | ||
3177 | pSMB->Reserved = 0; | ||
3178 | |||
3179 | param_count = 8; | ||
3180 | param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4; | ||
3181 | data_count = acllen; | ||
3182 | data_offset = param_offset + param_count; | ||
3183 | byte_count = 3 /* pad */ + param_count; | ||
3184 | |||
3185 | pSMB->DataCount = cpu_to_le32(data_count); | ||
3186 | pSMB->TotalDataCount = pSMB->DataCount; | ||
3187 | pSMB->MaxParameterCount = cpu_to_le32(4); | ||
3188 | pSMB->MaxDataCount = cpu_to_le32(16384); | ||
3189 | pSMB->ParameterCount = cpu_to_le32(param_count); | ||
3190 | pSMB->ParameterOffset = cpu_to_le32(param_offset); | ||
3191 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
3192 | pSMB->DataOffset = cpu_to_le32(data_offset); | ||
3193 | pSMB->SetupCount = 0; | ||
3194 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC); | ||
3195 | pSMB->ByteCount = cpu_to_le16(byte_count+data_count); | ||
3196 | |||
3197 | pSMB->Fid = fid; /* file handle always le */ | ||
3198 | pSMB->Reserved2 = 0; | ||
3199 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL); | ||
3200 | |||
3201 | if (pntsd && acllen) { | ||
3202 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, | ||
3203 | (char *) pntsd, | ||
3204 | acllen); | ||
3205 | pSMB->hdr.smb_buf_length += (byte_count + data_count); | ||
3206 | |||
3207 | } else | ||
3208 | pSMB->hdr.smb_buf_length += byte_count; | ||
3209 | |||
3210 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3211 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3212 | |||
3213 | cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc)); | ||
3214 | if (rc) | ||
3215 | cFYI(1, ("Set CIFS ACL returned %d", rc)); | ||
3216 | cifs_buf_release(pSMB); | ||
3217 | |||
3218 | if (rc == -EAGAIN) | ||
3219 | goto setCifsAclRetry; | ||
3220 | |||
3221 | return (rc); | ||
3222 | } | ||
3223 | |||
3159 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 3224 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
3160 | 3225 | ||
3161 | /* Legacy Query Path Information call for lookup to old servers such | 3226 | /* Legacy Query Path Information call for lookup to old servers such |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index e915eb1d2e66..fdc0fe109d7b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1607,7 +1607,13 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1607 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1607 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1608 | else if (attrs->ia_valid & ATTR_MODE) { | 1608 | else if (attrs->ia_valid & ATTR_MODE) { |
1609 | rc = 0; | 1609 | rc = 0; |
1610 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
1611 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | ||
1612 | rc = mode_to_acl(direntry->d_inode, full_path, mode); | ||
1613 | else if ((mode & S_IWUGO) == 0) /* not writeable */ { | ||
1614 | #else | ||
1610 | if ((mode & S_IWUGO) == 0) /* not writeable */ { | 1615 | if ((mode & S_IWUGO) == 0) /* not writeable */ { |
1616 | #endif | ||
1611 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 1617 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1612 | set_dosattr = TRUE; | 1618 | set_dosattr = TRUE; |
1613 | time_buf.Attributes = | 1619 | time_buf.Attributes = |
@@ -1626,10 +1632,10 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1626 | if (time_buf.Attributes == 0) | 1632 | if (time_buf.Attributes == 0) |
1627 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); | 1633 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); |
1628 | } | 1634 | } |
1629 | /* BB to be implemented - | 1635 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
1630 | via Windows security descriptors or streams */ | 1636 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
1631 | /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid, | 1637 | mode_to_acl(direntry->d_inode, full_path, mode); |
1632 | cifs_sb->local_nls); */ | 1638 | #endif |
1633 | } | 1639 | } |
1634 | 1640 | ||
1635 | if (attrs->ia_valid & ATTR_ATIME) { | 1641 | if (attrs->ia_valid & ATTR_ATIME) { |