Be stricter with copy_file_range probe results · model-checking/verify-rust-std@30c876c (original) (raw)

`@@ -607,42 +607,44 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->

`

607

607

`Ok(0) => return CopyResult::Ended(written), // reached EOF

`

608

608

`Ok(ret) => written += ret as u64,

`

609

609

`Err(err) => {

`

610

``

`-

let raw_os_error = match err.raw_os_error() {

`

611

``

`-

Some(raw) => raw,

`

612

``

`-

_ => return CopyResult::Error(err, written),

`

613

``

`-

};

`

614

``

`-

return match raw_os_error {

`

``

610

`+

return match err.raw_os_error() {

`

615

611

`// when file offset + max_length > u64::MAX

`

616

``

`-

EOVERFLOW => CopyResult::Fallback(written),

`

617

``

`-

ENOSYS | EXDEV | EINVAL | EPERM | EOPNOTSUPP | EBADF if written == 0 => {

`

``

612

`+

Some(EOVERFLOW) => CopyResult::Fallback(written),

`

``

613

`+

Some(raw_os_error @ (ENOSYS | EXDEV | EINVAL | EPERM | EOPNOTSUPP | EBADF))

`

``

614

`+

if written == 0 =>

`

``

615

`+

{

`

618

616

`if !have_probed {

`

619

``

`-

if raw_os_error == ENOSYS {

`

620

``

`-

HAS_COPY_FILE_RANGE.store(UNAVAILABLE, Ordering::Relaxed);

`

621

``

`-

} else {

`

622

``

`-

// EPERM can indicate seccomp filters or an

`

623

``

`-

// immutable file. To distinguish these cases

`

624

``

`-

// we probe with invalid file descriptors which

`

625

``

`-

// should result in EBADF if the syscall is

`

626

``

`-

// supported and some other error (ENOSYS or

`

627

``

`-

// EPERM) if it's not available.

`

628

``

`-

let result = unsafe {

`

629

``

`-

cvt(copy_file_range(

`

630

``

`-

INVALID_FD,

`

631

``

`-

ptr::null_mut(),

`

632

``

`-

INVALID_FD,

`

633

``

`-

ptr::null_mut(),

`

634

``

`-

1,

`

635

``

`-

0,

`

636

``

`-

))

`

637

``

`-

};

`

638

``

-

639

``

`-

if matches!(result.map_err(|e| e.raw_os_error()), Err(Some(EBADF)))

`

640

``

`-

{

`

641

``

`-

HAS_COPY_FILE_RANGE.store(AVAILABLE, Ordering::Relaxed);

`

642

``

`-

} else {

`

643

``

`-

HAS_COPY_FILE_RANGE.store(UNAVAILABLE, Ordering::Relaxed);

`

``

617

`+

let available = match raw_os_error {

`

``

618

`+

EPERM => {

`

``

619

`+

// EPERM can indicate seccomp filters or an

`

``

620

`+

// immutable file. To distinguish these

`

``

621

`+

// cases we probe with invalid file

`

``

622

`+

// descriptors which should result in EBADF

`

``

623

`+

// if the syscall is supported and EPERM or

`

``

624

`+

// ENOSYS if it's not available.

`

``

625

`+

match unsafe {

`

``

626

`+

cvt(copy_file_range(

`

``

627

`+

INVALID_FD,

`

``

628

`+

ptr::null_mut(),

`

``

629

`+

INVALID_FD,

`

``

630

`+

ptr::null_mut(),

`

``

631

`+

1,

`

``

632

`+

0,

`

``

633

`+

))

`

``

634

`+

.map_err(|e| e.raw_os_error())

`

``

635

`+

} {

`

``

636

`+

Err(Some(EPERM | ENOSYS)) => UNAVAILABLE,

`

``

637

`+

Err(Some(EBADF)) => AVAILABLE,

`

``

638

`+

Ok(_) => panic!("unexpected copy_file_range probe success"),

`

``

639

`+

// Treat other errors as the syscall

`

``

640

`+

// being unavailable.

`

``

641

`+

Err(_) => UNAVAILABLE,

`

``

642

`+

}

`

644

643

`}

`

645

``

`-

}

`

``

644

`+

ENOSYS => UNAVAILABLE,

`

``

645

`+

_ => AVAILABLE,

`

``

646

`+

};

`

``

647

`+

HAS_COPY_FILE_RANGE.store(available, Ordering::Relaxed);

`

646

648

`}

`

647

649

``

648

650

`// Try fallback io::copy if either:

`