Skip to content

Commit

Permalink
fs: bridge: Add missing Lseek whence checks
Browse files Browse the repository at this point in the history
The man page for lseek(2) says that the filesystem should
return an ENXIO when the offset is greater than the file
size on either SEEK_DATA or SEEK_HOLE or if the offset is
set to the end of the file with SEEK_DATA (where there is
an implicit hole). Adding these checks to the current Lseek
implementation.

Change-Id: I8db0913a9e37209e1681ffd11a9afb7f39810132
  • Loading branch information
turan18 authored and hanwen committed Oct 1, 2023
1 parent 385fb78 commit fc2c4d3
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
14 changes: 9 additions & 5 deletions fs/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -1175,18 +1175,22 @@ func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.Ls
out.Offset = off
return errnoToStatus(errno)
}

var attr fuse.AttrOut
if s := b.getattr(ctx, n, nil, &attr); s != 0 {
return errnoToStatus(s)
}
if in.Whence == _SEEK_DATA {
if in.Offset >= attr.Size {
return errnoToStatus(syscall.ENXIO)
}
out.Offset = in.Offset
return fuse.OK
}

if in.Whence == _SEEK_HOLE {
var attr fuse.AttrOut
if s := b.getattr(ctx, n, nil, &attr); s != 0 {
return errnoToStatus(s)
if in.Offset > attr.Size {
return errnoToStatus(syscall.ENXIO)
}

out.Offset = attr.Size
return fuse.OK
}
Expand Down
47 changes: 47 additions & 0 deletions posixtest/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package posixtest

import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -34,6 +35,7 @@ var All = map[string]func(*testing.T, string){
"Link": Link,
"LinkUnlinkRename": LinkUnlinkRename,
"LseekHoleSeeksToEOF": LseekHoleSeeksToEOF,
"LseekEnxioCheck": LseekEnxioCheck,
"RenameOverwriteDestNoExist": RenameOverwriteDestNoExist,
"RenameOverwriteDestExist": RenameOverwriteDestExist,
"RenameOpenDir": RenameOpenDir,
Expand Down Expand Up @@ -720,3 +722,48 @@ func LseekHoleSeeksToEOF(t *testing.T, mnt string) {
t.Errorf("got offset %d, want %d", off, len(content))
}
}

func LseekEnxioCheck(t *testing.T, mnt string) {
fn := filepath.Join(mnt, "file.bin")
content := bytes.Repeat([]byte("abcxyz\n"), 1024)
if err := ioutil.WriteFile(fn, content, 0644); err != nil {
t.Fatalf("WriteFile: %v", err)
}

fd, err := syscall.Open(fn, syscall.O_RDONLY, 0644)
if err != nil {
t.Fatalf("Open: %v", err)
}
defer syscall.Close(fd)

testCases := []struct {
name string
offset int64
whence int
}{
{
name: "Lseek SEEK_DATA where offset is at EOF returns ENXIO",
offset: int64(len(content)),
whence: unix.SEEK_DATA,
},
{
name: "Lseek SEEK_DATA where offset greater than EOF returns ENXIO",
offset: int64(len(content)) + 1,
whence: unix.SEEK_DATA,
},
{
name: "Lseek SEEK_HOLE where offset is greater than EOF returns ENXIO",
offset: int64(len(content)) + 1,
whence: unix.SEEK_HOLE,
},
}

for _, tc := range testCases {
_, err := unix.Seek(fd, tc.offset, tc.whence)
if err != nil {
if !errors.Is(err, syscall.ENXIO) {
t.Errorf("Failed test case: %s; got %v, want %v", tc.name, err, syscall.ENXIO)
}
}
}
}

0 comments on commit fc2c4d3

Please sign in to comment.