Ticket #6750: BugFix-6750-CheckPermissions-in-BFS.patch
File BugFix-6750-CheckPermissions-in-BFS.patch, 5.7 KB (added by , 13 years ago) |
---|
-
src/add-ons/kernel/file_systems/bfs/Inode.cpp
489 489 status_t 490 490 Inode::CheckPermissions(int accessMode) const 491 491 { 492 uid_t user = geteuid();493 gid_t group = getegid();494 495 492 // you never have write access to a read-only volume 496 493 if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly()) 497 494 return B_READ_ONLY_DEVICE; 498 495 499 // root users always have full access (but they can't execute files without 500 // any execute permissions set) 501 if (user == 0) { 502 if (!((accessMode & X_OK) != 0 && (Mode() & S_IXUSR) == 0) 503 || (Mode() & S_DIRECTORY) != 0) { 504 return B_OK; 505 } 506 } 507 508 // shift mode bits, to check directly against accessMode 496 // get node permissions 509 497 mode_t mode = Mode(); 510 if (user == (uid_t)fNode.UserID()) 511 mode >>= 6; 512 else if (group == (gid_t)fNode.GroupID()) 513 mode >>= 3; 498 int userPermissions = (mode & S_IRWXU) >> 6; 499 int groupPermissions = (mode & S_IRWXG) >> 3; 500 int otherPermissions = mode & S_IRWXO; 514 501 515 if (accessMode & ~(mode & S_IRWXO)) 516 return B_NOT_ALLOWED; 502 // get the node permissions for this uid/gid 503 int permissions = 0; 504 uid_t uid = geteuid(); 505 gid_t gid = getegid(); 517 506 518 return B_OK; 507 if (uid == 0) { 508 // user is root 509 // root has always read/write permission, but at least one of the 510 // X bits must be set for execute permission 511 permissions = userPermissions | groupPermissions | otherPermissions 512 | R_OK | W_OK; 513 } else if (uid == (uid_t)fNode.UserID()) { 514 // user is node owner 515 permissions = userPermissions; 516 } else if (gid == (gid_t)fNode.GroupID()) { 517 // user is in owning group 518 permissions = groupPermissions; 519 } else { 520 // user is one of the others 521 permissions = otherPermissions; 522 } 523 524 return (accessMode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; 519 525 } 520 526 521 527 -
src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
778 778 // TODO: we should definitely check a bit more if the new stats are 779 779 // valid - or even better, the VFS should check this before calling us 780 780 781 status_t status = inode->CheckPermissions(W_OK); 782 if (status < B_OK) 783 RETURN_ERROR(status); 781 bfs_inode& node = inode->Node(); 782 bool updateTime = false; 783 uid_t uid = geteuid(); 784 785 bool isOwnerOrRoot = uid == 0 || uid == (uid_t)node.UserID(); 786 bool hasWriteAccess = inode->CheckPermissions(W_OK) == B_OK; 784 787 785 788 Transaction transaction(volume, inode->BlockNumber()); 786 789 inode->WriteLockInTransaction(transaction); 787 790 788 bfs_inode& node = inode->Node();789 bool updateTime = false;790 791 791 if ((mask & B_STAT_SIZE) != 0) { 792 792 // Since WSTAT_SIZE is the only thing that can fail directly, we 793 793 // do it first, so that the inode state will still be consistent … … 798 798 return B_BAD_VALUE; 799 799 800 800 if (inode->Size() != stat->st_size) { 801 if (!hasWriteAccess) 802 RETURN_ERROR(B_NOT_ALLOWED); 801 803 off_t oldSize = inode->Size(); 802 804 803 status = inode->SetFileSize(transaction, stat->st_size);805 status_t status = inode->SetFileSize(transaction, stat->st_size); 804 806 if (status != B_OK) 805 807 return status; 806 808 … … 822 824 } 823 825 } 824 826 827 if ((mask & B_STAT_UID) != 0) { 828 // only root should be allowed 829 if (uid != 0) 830 RETURN_ERROR(B_NOT_ALLOWED); 831 node.uid = HOST_ENDIAN_TO_BFS_INT32(stat->st_uid); 832 updateTime = true; 833 } 834 835 if ((mask & B_STAT_GID) != 0) { 836 // only the user or root can do that 837 if (!isOwnerOrRoot) 838 RETURN_ERROR(B_NOT_ALLOWED); 839 node.gid = HOST_ENDIAN_TO_BFS_INT32(stat->st_gid); 840 updateTime = true; 841 } 842 825 843 if ((mask & B_STAT_MODE) != 0) { 844 // only the user or root can do that 845 if (!isOwnerOrRoot) 846 RETURN_ERROR(B_NOT_ALLOWED); 826 847 PRINT(("original mode = %ld, stat->st_mode = %d\n", node.Mode(), 827 848 stat->st_mode)); 828 849 node.mode = HOST_ENDIAN_TO_BFS_INT32((node.Mode() & ~S_IUMSK) … … 830 851 updateTime = true; 831 852 } 832 853 833 if ((mask & B_STAT_UID) != 0) { 834 node.uid = HOST_ENDIAN_TO_BFS_INT32(stat->st_uid); 835 updateTime = true; 854 if ((mask & B_STAT_CREATION_TIME) != 0) { 855 // the user or root can do that or any user with write access 856 if (!isOwnerOrRoot && !hasWriteAccess) 857 RETURN_ERROR(B_NOT_ALLOWED); 858 node.create_time 859 = HOST_ENDIAN_TO_BFS_INT64(bfs_inode::ToInode(stat->st_crtim)); 836 860 } 837 if ((mask & B_STAT_GID) != 0) {838 node.gid = HOST_ENDIAN_TO_BFS_INT32(stat->st_gid);839 updateTime = true;840 }841 861 842 862 if ((mask & B_STAT_MODIFICATION_TIME) != 0) { 863 // the user or root can do that or any user with write access 864 if (!isOwnerOrRoot && !hasWriteAccess) 865 RETURN_ERROR(B_NOT_ALLOWED); 843 866 if (!inode->InLastModifiedIndex()) { 844 867 // directory modification times are not part of the index 845 868 node.last_modified_time … … 851 874 bfs_inode::ToInode(stat->st_mtim)); 852 875 } 853 876 } 854 if ((mask & B_STAT_CREATION_TIME) != 0) { 855 node.create_time 856 = HOST_ENDIAN_TO_BFS_INT64(bfs_inode::ToInode(stat->st_crtim)); 857 } 877 858 878 if ((mask & B_STAT_CHANGE_TIME) != 0 || updateTime) { 879 // the user or root can do that or any user with write access 880 if (!isOwnerOrRoot && !hasWriteAccess) 881 RETURN_ERROR(B_NOT_ALLOWED); 859 882 bigtime_t newTime; 860 883 if ((mask & B_STAT_CHANGE_TIME) == 0) 861 884 newTime = bfs_inode::ToInode(real_time_clock_usecs()); … … 865 888 node.status_change_time = HOST_ENDIAN_TO_BFS_INT64(newTime); 866 889 } 867 890 868 status = inode->WriteBack(transaction);891 status_t status = inode->WriteBack(transaction); 869 892 if (status == B_OK) 870 893 status = transaction.Done(); 871 894 if (status == B_OK)