aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsacl.c100
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/inode.c2
3 files changed, 55 insertions, 51 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 57ecdc83c26f..7f8e6c46d116 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -552,67 +552,66 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
552 return rc; 552 return rc;
553} 553}
554 554
555 555static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
556/* Retrieve an ACL from the server */ 556 __u16 fid, u32 *pacllen)
557static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
558 const char *path, const __u16 *pfid)
559{ 557{
560 struct cifsFileInfo *open_file = NULL;
561 bool unlock_file = false;
562 int xid;
563 int rc = -EIO;
564 __u16 fid;
565 struct super_block *sb;
566 struct cifs_sb_info *cifs_sb;
567 struct cifs_ntsd *pntsd = NULL; 558 struct cifs_ntsd *pntsd = NULL;
559 int xid, rc;
568 560
569 cFYI(1, ("get mode from ACL for %s", path)); 561 xid = GetXid();
562 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
563 FreeXid(xid);
570 564
571 if (inode == NULL)
572 return NULL;
573 565
574 xid = GetXid(); 566 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
575 if (pfid == NULL) 567 return pntsd;
576 open_file = find_readable_file(CIFS_I(inode)); 568}
577 else
578 fid = *pfid;
579 569
580 sb = inode->i_sb; 570static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
581 if (sb == NULL) { 571 const char *path, u32 *pacllen)
582 FreeXid(xid); 572{
583 return NULL; 573 struct cifs_ntsd *pntsd = NULL;
584 } 574 int oplock = 0;
585 cifs_sb = CIFS_SB(sb); 575 int xid, rc;
576 __u16 fid;
586 577
587 if (open_file) { 578 xid = GetXid();
588 unlock_file = true; 579
589 fid = open_file->netfid; 580 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
590 } else if (pfid == NULL) { 581 &fid, &oplock, NULL, cifs_sb->local_nls,
591 int oplock = 0; 582 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
592 /* open file */ 583 if (rc) {
593 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, 584 cERROR(1, ("Unable to open file to get ACL"));
594 READ_CONTROL, 0, &fid, &oplock, NULL, 585 goto out;
595 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
596 CIFS_MOUNT_MAP_SPECIAL_CHR);
597 if (rc != 0) {
598 cERROR(1, ("Unable to open file to get ACL"));
599 FreeXid(xid);
600 return NULL;
601 }
602 } 586 }
603 587
604 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); 588 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
605 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); 589 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
606 if (unlock_file == true) /* find_readable_file increments ref count */
607 atomic_dec(&open_file->wrtPending);
608 else if (pfid == NULL) /* if opened above we have to close the handle */
609 CIFSSMBClose(xid, cifs_sb->tcon, fid);
610 /* else handle was passed in by caller */
611 590
591 CIFSSMBClose(xid, cifs_sb->tcon, fid);
592 out:
612 FreeXid(xid); 593 FreeXid(xid);
613 return pntsd; 594 return pntsd;
614} 595}
615 596
597/* Retrieve an ACL from the server */
598static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
599 struct inode *inode, const char *path,
600 u32 *pacllen)
601{
602 struct cifs_ntsd *pntsd = NULL;
603 struct cifsFileInfo *open_file = NULL;
604
605 if (inode)
606 open_file = find_readable_file(CIFS_I(inode));
607 if (!open_file)
608 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
609
610 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
611 atomic_dec(&open_file->wrtPending);
612 return pntsd;
613}
614
616/* Set an ACL on the server */ 615/* Set an ACL on the server */
617static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, 616static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
618 struct inode *inode, const char *path) 617 struct inode *inode, const char *path)
@@ -668,14 +667,19 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
668} 667}
669 668
670/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ 669/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
671void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid) 670void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
671 const char *path, const __u16 *pfid)
672{ 672{
673 struct cifs_ntsd *pntsd = NULL; 673 struct cifs_ntsd *pntsd = NULL;
674 u32 acllen = 0; 674 u32 acllen = 0;
675 int rc = 0; 675 int rc = 0;
676 676
677 cFYI(DBG2, ("converting ACL to mode for %s", path)); 677 cFYI(DBG2, ("converting ACL to mode for %s", path));
678 pntsd = get_cifs_acl(&acllen, inode, path, pfid); 678
679 if (pfid)
680 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
681 else
682 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
679 683
680 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ 684 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
681 if (pntsd) 685 if (pntsd)
@@ -698,7 +702,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
698 cFYI(DBG2, ("set ACL from mode for %s", path)); 702 cFYI(DBG2, ("set ACL from mode for %s", path));
699 703
700 /* Get the security descriptor */ 704 /* Get the security descriptor */
701 pntsd = get_cifs_acl(&secdesclen, inode, path, NULL); 705 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
702 706
703 /* Add three ACEs for owner, group, everyone getting rid of 707 /* Add three ACEs for owner, group, everyone getting rid of
704 other ACEs as chmod disables ACEs and set the security descriptor */ 708 other ACEs as chmod disables ACEs and set the security descriptor */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index d542cf1f69c3..f9452329bcce 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -108,8 +108,8 @@ extern int cifs_get_inode_info(struct inode **pinode,
108extern int cifs_get_inode_info_unix(struct inode **pinode, 108extern int cifs_get_inode_info_unix(struct inode **pinode,
109 const unsigned char *search_path, 109 const unsigned char *search_path,
110 struct super_block *sb, int xid); 110 struct super_block *sb, int xid);
111extern void acl_to_uid_mode(struct inode *inode, const char *path, 111extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
112 const __u16 *pfid); 112 const char *path, const __u16 *pfid);
113extern int mode_to_acl(struct inode *inode, const char *path, __u64); 113extern int mode_to_acl(struct inode *inode, const char *path, __u64);
114 114
115extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, 115extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 84b7bea73674..fad882b075ba 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -626,7 +626,7 @@ int cifs_get_inode_info(struct inode **pinode,
626 /* fill in 0777 bits from ACL */ 626 /* fill in 0777 bits from ACL */
627 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 627 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
628 cFYI(1, ("Getting mode bits from ACL")); 628 cFYI(1, ("Getting mode bits from ACL"));
629 acl_to_uid_mode(inode, full_path, pfid); 629 acl_to_uid_mode(cifs_sb, inode, full_path, pfid);
630 } 630 }
631#endif 631#endif
632 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { 632 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {