Ticket #6750: BugFix-6750-CheckPermissions-in-BFS.patch

File BugFix-6750-CheckPermissions-in-BFS.patch, 5.7 KB (added by rohityadav, 13 years ago)

Fixes chmod issue in BFS (new)

  • src/add-ons/kernel/file_systems/bfs/Inode.cpp

     
    489489status_t
    490490Inode::CheckPermissions(int accessMode) const
    491491{
    492     uid_t user = geteuid();
    493     gid_t group = getegid();
    494 
    495492    // you never have write access to a read-only volume
    496493    if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly())
    497494        return B_READ_ONLY_DEVICE;
    498495
    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
    509497    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;
    514501
    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();
    517506
    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;
    519525}
    520526
    521527
  • src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp

     
    778778    // TODO: we should definitely check a bit more if the new stats are
    779779    //  valid - or even better, the VFS should check this before calling us
    780780
    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;
    784787
    785788    Transaction transaction(volume, inode->BlockNumber());
    786789    inode->WriteLockInTransaction(transaction);
    787790
    788     bfs_inode& node = inode->Node();
    789     bool updateTime = false;
    790 
    791791    if ((mask & B_STAT_SIZE) != 0) {
    792792        // Since WSTAT_SIZE is the only thing that can fail directly, we
    793793        // do it first, so that the inode state will still be consistent
     
    798798            return B_BAD_VALUE;
    799799
    800800        if (inode->Size() != stat->st_size) {
     801            if (!hasWriteAccess)
     802                RETURN_ERROR(B_NOT_ALLOWED);
    801803            off_t oldSize = inode->Size();
    802804
    803             status = inode->SetFileSize(transaction, stat->st_size);
     805            status_t status = inode->SetFileSize(transaction, stat->st_size);
    804806            if (status != B_OK)
    805807                return status;
    806808
     
    822824        }
    823825    }
    824826
     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
    825843    if ((mask & B_STAT_MODE) != 0) {
     844        // only the user or root can do that
     845        if (!isOwnerOrRoot)
     846            RETURN_ERROR(B_NOT_ALLOWED);
    826847        PRINT(("original mode = %ld, stat->st_mode = %d\n", node.Mode(),
    827848            stat->st_mode));
    828849        node.mode = HOST_ENDIAN_TO_BFS_INT32((node.Mode() & ~S_IUMSK)
     
    830851        updateTime = true;
    831852    }
    832853
    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));
    836860    }
    837     if ((mask & B_STAT_GID) != 0) {
    838         node.gid = HOST_ENDIAN_TO_BFS_INT32(stat->st_gid);
    839         updateTime = true;
    840     }
    841861
    842862    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);
    843866        if (!inode->InLastModifiedIndex()) {
    844867            // directory modification times are not part of the index
    845868            node.last_modified_time
     
    851874                bfs_inode::ToInode(stat->st_mtim));
    852875        }
    853876    }
    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
    858878    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);
    859882        bigtime_t newTime;
    860883        if ((mask & B_STAT_CHANGE_TIME) == 0)
    861884            newTime = bfs_inode::ToInode(real_time_clock_usecs());
     
    865888        node.status_change_time = HOST_ENDIAN_TO_BFS_INT64(newTime);
    866889    }
    867890
    868     status = inode->WriteBack(transaction);
     891    status_t status = inode->WriteBack(transaction);
    869892    if (status == B_OK)
    870893        status = transaction.Done();
    871894    if (status == B_OK)