Ticket #6750: BugFix-6750-CheckPermissions-in-ext2fs.patch
File BugFix-6750-CheckPermissions-in-ext2fs.patch, 4.9 KB (added by , 13 years ago) |
---|
-
src/add-ons/kernel/file_systems/ext2/Inode.cpp
6 6 7 7 #include "Inode.h" 8 8 9 #include <fs_cache.h>10 9 #include <string.h> 11 10 #include <util/AutoLock.h> 11 #include <NodeMonitor.h> 12 12 13 13 #include "CachedBlock.h" 14 14 #include "DataStream.h" … … 187 187 status_t 188 188 Inode::CheckPermissions(int accessMode) const 189 189 { 190 uid_t user = geteuid();191 gid_t group = getegid();192 193 190 // you never have write access to a read-only volume 194 if ( accessMode & W_OK&& fVolume->IsReadOnly())191 if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly()) 195 192 return B_READ_ONLY_DEVICE; 196 193 197 // root users always have full access (but they can't execute files without 198 // any execute permissions set) 199 if (user == 0) { 200 if (!((accessMode & X_OK) != 0 && (Mode() & S_IXUSR) == 0) 201 || S_ISDIR(Mode())) 202 return B_OK; 203 } 204 205 // shift mode bits, to check directly against accessMode 194 // get node permissions 206 195 mode_t mode = Mode(); 207 if (user == (uid_t)fNode.UserID()) 208 mode >>= 6; 209 else if (group == (gid_t)fNode.GroupID()) 210 mode >>= 3; 196 int userPermissions = (mode & S_IRWXU) >> 6; 197 int groupPermissions = (mode & S_IRWXG) >> 3; 198 int otherPermissions = mode & S_IRWXO; 211 199 212 if (accessMode & ~(mode & S_IRWXO)) 213 return B_NOT_ALLOWED; 200 // get the node permissions for this uid/gid 201 int permissions = 0; 202 uid_t uid = geteuid(); 203 gid_t gid = getegid(); 214 204 215 return B_OK; 205 if (uid == 0) { 206 // user is root 207 // root has always read/write permission, but at least one of the 208 // X bits must be set for execute permission 209 permissions = userPermissions | groupPermissions | otherPermissions 210 | R_OK | W_OK; 211 } else if (uid == (uid_t)fNode.UserID()) { 212 // user is node owner 213 permissions = userPermissions; 214 } else if (gid == (gid_t)fNode.GroupID()) { 215 // user is in owning group 216 permissions = groupPermissions; 217 } else { 218 // user is one of the others 219 permissions = otherPermissions; 220 } 221 222 return (accessMode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; 216 223 } 217 224 218 225 -
src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp
580 580 581 581 Inode* inode = (Inode*)_node->private_node; 582 582 583 status_t status = inode->CheckPermissions(W_OK); 584 if (status < B_OK) 585 return status; 583 ext2_inode& node = inode->Node(); 584 bool updateTime = false; 585 uid_t uid = geteuid(); 586 587 bool isOwnerOrRoot = uid == 0 || uid == (uid_t)node.UserID(); 588 bool hasWriteAccess = inode->CheckPermissions(W_OK) == B_OK; 586 589 587 590 TRACE("ext2_write_stat: Starting transaction\n"); 588 591 Transaction transaction(volume->GetJournal()); 589 592 inode->WriteLockInTransaction(transaction); 590 593 591 bool updateTime = false;592 593 594 if ((mask & B_STAT_SIZE) != 0) { 594 595 if (inode->IsDirectory()) 595 596 return B_IS_A_DIRECTORY; … … 599 600 TRACE("ext2_write_stat: Old size: %ld, new size: %ld\n", 600 601 (long)inode->Size(), (long)stat->st_size); 601 602 if (inode->Size() != stat->st_size) { 603 if (!hasWriteAccess) 604 return B_NOT_ALLOWED; 602 605 off_t oldSize = inode->Size(); 603 606 604 status = inode->Resize(transaction, stat->st_size);607 status_t status = inode->Resize(transaction, stat->st_size); 605 608 if(status != B_OK) 606 609 return status; 607 610 … … 615 618 } 616 619 } 617 620 618 ext2_inode& node = inode->Node();619 620 621 if ((mask & B_STAT_MODE) != 0) { 622 // only the user or root can do that 623 if (!isOwnerOrRoot) 624 return B_NOT_ALLOWED; 621 625 node.UpdateMode(stat->st_mode, S_IUMSK); 622 626 updateTime = true; 623 627 } 624 628 625 629 if ((mask & B_STAT_UID) != 0) { 630 // only root should be allowed 631 if (uid != 0) 632 return B_NOT_ALLOWED; 626 633 node.SetUserID(stat->st_uid); 627 634 updateTime = true; 628 635 } 636 629 637 if ((mask & B_STAT_GID) != 0) { 638 // only the user or root can do that 639 if (!isOwnerOrRoot) 640 return B_NOT_ALLOWED; 630 641 node.SetGroupID(stat->st_gid); 631 642 updateTime = true; 632 643 } 633 644 634 645 if ((mask & B_STAT_MODIFICATION_TIME) != 0 || updateTime 635 646 || (mask & B_STAT_CHANGE_TIME) != 0) { 647 // the user or root can do that or any user with write access 648 if (!isOwnerOrRoot && !hasWriteAccess) 649 return B_NOT_ALLOWED; 636 650 struct timespec newTimespec = { 0, 0}; 637 651 638 652 if ((mask & B_STAT_MODIFICATION_TIME) != 0) … … 647 661 648 662 inode->SetModificationTime(&newTimespec); 649 663 } 650 if ((mask & B_STAT_CREATION_TIME) != 0) 664 if ((mask & B_STAT_CREATION_TIME) != 0) { 665 // the user or root can do that or any user with write access 666 if (!isOwnerOrRoot && !hasWriteAccess) 667 return B_NOT_ALLOWED; 651 668 inode->SetCreationTime(&stat->st_crtim); 669 } 652 670 653 status = inode->WriteBack(transaction);671 status_t status = inode->WriteBack(transaction); 654 672 if (status == B_OK) 655 673 status = transaction.Done(); 656 674 if (status == B_OK)