diff options
Diffstat (limited to 'fs/cifs/cifsacl.c')
-rw-r--r-- | fs/cifs/cifsacl.c | 178 |
1 files changed, 93 insertions, 85 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 57ecdc83c26f..1403b5d86a73 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -552,130 +552,138 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, | |||
552 | return rc; | 552 | return rc; |
553 | } | 553 | } |
554 | 554 | ||
555 | 555 | static 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) |
557 | static 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; | ||
560 | |||
561 | xid = GetXid(); | ||
562 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); | ||
563 | FreeXid(xid); | ||
568 | 564 | ||
569 | cFYI(1, ("get mode from ACL for %s", path)); | ||
570 | 565 | ||
571 | if (inode == NULL) | 566 | cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); |
572 | return NULL; | 567 | return pntsd; |
568 | } | ||
569 | |||
570 | static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | ||
571 | const char *path, u32 *pacllen) | ||
572 | { | ||
573 | struct cifs_ntsd *pntsd = NULL; | ||
574 | int oplock = 0; | ||
575 | int xid, rc; | ||
576 | __u16 fid; | ||
573 | 577 | ||
574 | xid = GetXid(); | 578 | xid = GetXid(); |
575 | if (pfid == NULL) | ||
576 | open_file = find_readable_file(CIFS_I(inode)); | ||
577 | else | ||
578 | fid = *pfid; | ||
579 | 579 | ||
580 | sb = inode->i_sb; | 580 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0, |
581 | if (sb == NULL) { | 581 | &fid, &oplock, NULL, cifs_sb->local_nls, |
582 | FreeXid(xid); | 582 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
583 | return NULL; | 583 | if (rc) { |
584 | } | 584 | cERROR(1, ("Unable to open file to get ACL")); |
585 | cifs_sb = CIFS_SB(sb); | 585 | goto out; |
586 | |||
587 | if (open_file) { | ||
588 | unlock_file = true; | ||
589 | fid = open_file->netfid; | ||
590 | } else if (pfid == NULL) { | ||
591 | int oplock = 0; | ||
592 | /* open file */ | ||
593 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, | ||
594 | READ_CONTROL, 0, &fid, &oplock, NULL, | ||
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 | ||
616 | /* Set an ACL on the server */ | 597 | /* Retrieve an ACL from the server */ |
617 | static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | 598 | static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, |
618 | struct inode *inode, const char *path) | 599 | struct inode *inode, const char *path, |
600 | u32 *pacllen) | ||
619 | { | 601 | { |
620 | struct cifsFileInfo *open_file; | 602 | struct cifs_ntsd *pntsd = NULL; |
621 | bool unlock_file = false; | 603 | struct cifsFileInfo *open_file = NULL; |
622 | int xid; | ||
623 | int rc = -EIO; | ||
624 | __u16 fid; | ||
625 | struct super_block *sb; | ||
626 | struct cifs_sb_info *cifs_sb; | ||
627 | 604 | ||
628 | cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode)); | 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); | ||
629 | 609 | ||
630 | if (!inode) | 610 | pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen); |
631 | return rc; | 611 | atomic_dec(&open_file->wrtPending); |
612 | return pntsd; | ||
613 | } | ||
632 | 614 | ||
633 | sb = inode->i_sb; | 615 | static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid, |
634 | if (sb == NULL) | 616 | struct cifs_ntsd *pnntsd, u32 acllen) |
635 | return rc; | 617 | { |
618 | int xid, rc; | ||
636 | 619 | ||
637 | cifs_sb = CIFS_SB(sb); | ||
638 | xid = GetXid(); | 620 | xid = GetXid(); |
621 | rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); | ||
622 | FreeXid(xid); | ||
639 | 623 | ||
640 | open_file = find_readable_file(CIFS_I(inode)); | 624 | cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); |
641 | if (open_file) { | 625 | return rc; |
642 | unlock_file = true; | 626 | } |
643 | fid = open_file->netfid; | 627 | |
644 | } else { | 628 | static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, |
645 | int oplock = 0; | 629 | struct cifs_ntsd *pnntsd, u32 acllen) |
646 | /* open file */ | 630 | { |
647 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, | 631 | int oplock = 0; |
648 | WRITE_DAC, 0, &fid, &oplock, NULL, | 632 | int xid, rc; |
649 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 633 | __u16 fid; |
650 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 634 | |
651 | if (rc != 0) { | 635 | xid = GetXid(); |
652 | cERROR(1, ("Unable to open file to set ACL")); | 636 | |
653 | FreeXid(xid); | 637 | rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0, |
654 | return rc; | 638 | &fid, &oplock, NULL, cifs_sb->local_nls, |
655 | } | 639 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
640 | if (rc) { | ||
641 | cERROR(1, ("Unable to open file to set ACL")); | ||
642 | goto out; | ||
656 | } | 643 | } |
657 | 644 | ||
658 | rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); | 645 | rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); |
659 | cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); | 646 | cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); |
660 | if (unlock_file) | ||
661 | atomic_dec(&open_file->wrtPending); | ||
662 | else | ||
663 | CIFSSMBClose(xid, cifs_sb->tcon, fid); | ||
664 | 647 | ||
648 | CIFSSMBClose(xid, cifs_sb->tcon, fid); | ||
649 | out: | ||
665 | FreeXid(xid); | 650 | FreeXid(xid); |
651 | return rc; | ||
652 | } | ||
666 | 653 | ||
654 | /* Set an ACL on the server */ | ||
655 | static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | ||
656 | struct inode *inode, const char *path) | ||
657 | { | ||
658 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
659 | struct cifsFileInfo *open_file; | ||
660 | int rc; | ||
661 | |||
662 | cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode)); | ||
663 | |||
664 | open_file = find_readable_file(CIFS_I(inode)); | ||
665 | if (!open_file) | ||
666 | return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen); | ||
667 | |||
668 | rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen); | ||
669 | atomic_dec(&open_file->wrtPending); | ||
667 | return rc; | 670 | return rc; |
668 | } | 671 | } |
669 | 672 | ||
670 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 673 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
671 | void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid) | 674 | void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, |
675 | const char *path, const __u16 *pfid) | ||
672 | { | 676 | { |
673 | struct cifs_ntsd *pntsd = NULL; | 677 | struct cifs_ntsd *pntsd = NULL; |
674 | u32 acllen = 0; | 678 | u32 acllen = 0; |
675 | int rc = 0; | 679 | int rc = 0; |
676 | 680 | ||
677 | cFYI(DBG2, ("converting ACL to mode for %s", path)); | 681 | cFYI(DBG2, ("converting ACL to mode for %s", path)); |
678 | pntsd = get_cifs_acl(&acllen, inode, path, pfid); | 682 | |
683 | if (pfid) | ||
684 | pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen); | ||
685 | else | ||
686 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); | ||
679 | 687 | ||
680 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 688 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
681 | if (pntsd) | 689 | if (pntsd) |
@@ -698,7 +706,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | |||
698 | cFYI(DBG2, ("set ACL from mode for %s", path)); | 706 | cFYI(DBG2, ("set ACL from mode for %s", path)); |
699 | 707 | ||
700 | /* Get the security descriptor */ | 708 | /* Get the security descriptor */ |
701 | pntsd = get_cifs_acl(&secdesclen, inode, path, NULL); | 709 | pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen); |
702 | 710 | ||
703 | /* Add three ACEs for owner, group, everyone getting rid of | 711 | /* Add three ACEs for owner, group, everyone getting rid of |
704 | other ACEs as chmod disables ACEs and set the security descriptor */ | 712 | other ACEs as chmod disables ACEs and set the security descriptor */ |