2019-04-29 21:25:05 +00:00
// Copyright 2018 The gVisor Authors.
2018-04-27 17:37:02 +00:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package host
import (
"fmt"
"syscall"
2019-06-13 23:49:09 +00:00
"gvisor.dev/gvisor/pkg/sentry/context"
"gvisor.dev/gvisor/pkg/sentry/device"
"gvisor.dev/gvisor/pkg/sentry/fs"
2018-04-27 17:37:02 +00:00
)
// beforeSave is invoked by stateify.
func ( i * inodeFileState ) beforeSave ( ) {
if ! i . queue . IsEmpty ( ) {
panic ( "event queue must be empty" )
}
if ! i . descriptor . donated && i . sattr . Type == fs . RegularFile {
uattr , err := i . unstableAttr ( context . Background ( ) )
if err != nil {
2018-08-22 20:18:21 +00:00
panic ( fs . ErrSaveRejection { fmt . Errorf ( "failed to get unstable atttribute of %s: %v" , i . mops . inodeMappings [ i . sattr . InodeID ] , err ) } )
2018-04-27 17:37:02 +00:00
}
i . savedUAttr = & uattr
}
}
// afterLoad is invoked by stateify.
func ( i * inodeFileState ) afterLoad ( ) {
// Initialize the descriptor value.
if err := i . descriptor . initAfterLoad ( i . mops , i . sattr . InodeID , & i . queue ) ; err != nil {
panic ( fmt . Sprintf ( "failed to load value of descriptor: %v" , err ) )
}
// Remap the inode number.
var s syscall . Stat_t
if err := syscall . Fstat ( i . FD ( ) , & s ) ; err != nil {
2018-08-22 20:18:21 +00:00
panic ( fs . ErrCorruption { fmt . Errorf ( "failed to get metadata for fd %d: %v" , i . FD ( ) , err ) } )
2018-04-27 17:37:02 +00:00
}
key := device . MultiDeviceKey {
Device : s . Dev ,
Inode : s . Ino ,
}
if ! hostFileDevice . Load ( key , i . sattr . InodeID ) {
// This means there was a conflict at s.Dev and s.Ino with
// another inode mapping: two files that were unique on the
// saved filesystem are no longer unique on this filesystem.
// Since this violates the contract that filesystems cannot
// change across save and restore, error out.
2018-05-08 18:36:11 +00:00
panic ( fs . ErrCorruption { fmt . Errorf ( "host %s conflict in host device mappings: %s" , key , hostFileDevice ) } )
2018-04-27 17:37:02 +00:00
}
if ! i . descriptor . donated && i . sattr . Type == fs . RegularFile {
env , ok := fs . CurrentRestoreEnvironment ( )
if ! ok {
panic ( "missing restore environment" )
}
uattr := unstableAttr ( i . mops , & s )
if env . ValidateFileSize && uattr . Size != i . savedUAttr . Size {
2018-05-08 18:36:11 +00:00
panic ( fs . ErrCorruption { fmt . Errorf ( "file size has changed for %s: previously %d, now %d" , i . mops . inodeMappings [ i . sattr . InodeID ] , i . savedUAttr . Size , uattr . Size ) } )
2018-04-27 17:37:02 +00:00
}
if env . ValidateFileTimestamp && uattr . ModificationTime != i . savedUAttr . ModificationTime {
2018-05-08 18:36:11 +00:00
panic ( fs . ErrCorruption { fmt . Errorf ( "file modification time has changed for %s: previously %v, now %v" , i . mops . inodeMappings [ i . sattr . InodeID ] , i . savedUAttr . ModificationTime , uattr . ModificationTime ) } )
2018-04-27 17:37:02 +00:00
}
i . savedUAttr = nil
}
}