SetStat implements kernfs.Inode.SetStat. +checklocksignore
(ctx context.Context, fs *vfs.Filesystem, creds *auth.Credentials, opts vfs.SetStatOptions)
| 579 | // |
| 580 | // +checklocksignore |
| 581 | func (i *inode) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *auth.Credentials, opts vfs.SetStatOptions) error { |
| 582 | if i.readonly { |
| 583 | return linuxerr.EPERM |
| 584 | } |
| 585 | |
| 586 | s := &opts.Stat |
| 587 | |
| 588 | m := s.Mask |
| 589 | if m == 0 { |
| 590 | return nil |
| 591 | } |
| 592 | supportedModes := uint32(linux.STATX_MODE | linux.STATX_SIZE | linux.STATX_ATIME | linux.STATX_MTIME) |
| 593 | if i.virtualOwner.enabled { |
| 594 | if m&virtualOwnerModes != 0 { |
| 595 | // Take lock if any of the virtual owner fields will be updated. |
| 596 | i.virtualOwner.mu.Lock() |
| 597 | defer i.virtualOwner.mu.Unlock() |
| 598 | } |
| 599 | |
| 600 | supportedModes |= virtualOwnerModes |
| 601 | } |
| 602 | if m&^supportedModes != 0 { |
| 603 | return linuxerr.EPERM |
| 604 | } |
| 605 | |
| 606 | var hostStat unix.Stat_t |
| 607 | if err := i.stat(&hostStat); err != nil { |
| 608 | return err |
| 609 | } |
| 610 | if err := vfs.CheckSetStat(ctx, creds, &opts, linux.FileMode(hostStat.Mode), auth.KUID(hostStat.Uid), auth.KGID(hostStat.Gid)); err != nil { |
| 611 | return err |
| 612 | } |
| 613 | |
| 614 | if m&linux.STATX_MODE != 0 { |
| 615 | if i.virtualOwner.enabled { |
| 616 | // We hold i.virtualOwner.mu. |
| 617 | i.virtualOwner.mode = atomicbitops.FromUint32(uint32(opts.Stat.Mode)) |
| 618 | } else { |
| 619 | log.Warningf("sentry seccomp filters don't allow making fchmod(2) syscall") |
| 620 | return unix.EPERM |
| 621 | } |
| 622 | } |
| 623 | if m&linux.STATX_SIZE != 0 { |
| 624 | if hostStat.Mode&linux.S_IFMT != linux.S_IFREG { |
| 625 | return linuxerr.EINVAL |
| 626 | } |
| 627 | if err := unix.Ftruncate(i.hostFD, int64(s.Size)); err != nil { |
| 628 | return err |
| 629 | } |
| 630 | oldSize := uint64(hostStat.Size) |
| 631 | if s.Size < oldSize { |
| 632 | oldpgend, _ := hostarch.PageRoundUp(oldSize) |
| 633 | newpgend, _ := hostarch.PageRoundUp(s.Size) |
| 634 | if oldpgend != newpgend { |
| 635 | i.mapsMu.Lock() |
| 636 | i.mappings.Invalidate(memmap.MappableRange{newpgend, oldpgend}, memmap.InvalidateOpts{ |
| 637 | // Compare Linux's mm/truncate.c:truncate_setsize() => |
| 638 | // truncate_pagecache() => |
nothing calls this directly
no test coverage detected