Commit fc2c4d3d authored by Yasin Turan's avatar Yasin Turan Committed by Han-Wen Nienhuys

fs: bridge: Add missing Lseek whence checks

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
parent 385fb783
...@@ -1175,18 +1175,22 @@ func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.Ls ...@@ -1175,18 +1175,22 @@ func (b *rawBridge) Lseek(cancel <-chan struct{}, in *fuse.LseekIn, out *fuse.Ls
out.Offset = off out.Offset = off
return errnoToStatus(errno) 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.Whence == _SEEK_DATA {
if in.Offset >= attr.Size {
return errnoToStatus(syscall.ENXIO)
}
out.Offset = in.Offset out.Offset = in.Offset
return fuse.OK return fuse.OK
} }
if in.Whence == _SEEK_HOLE { if in.Whence == _SEEK_HOLE {
var attr fuse.AttrOut if in.Offset > attr.Size {
if s := b.getattr(ctx, n, nil, &attr); s != 0 { return errnoToStatus(syscall.ENXIO)
return errnoToStatus(s)
} }
out.Offset = attr.Size out.Offset = attr.Size
return fuse.OK return fuse.OK
} }
......
...@@ -7,6 +7,7 @@ package posixtest ...@@ -7,6 +7,7 @@ package posixtest
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
...@@ -34,6 +35,7 @@ var All = map[string]func(*testing.T, string){ ...@@ -34,6 +35,7 @@ var All = map[string]func(*testing.T, string){
"Link": Link, "Link": Link,
"LinkUnlinkRename": LinkUnlinkRename, "LinkUnlinkRename": LinkUnlinkRename,
"LseekHoleSeeksToEOF": LseekHoleSeeksToEOF, "LseekHoleSeeksToEOF": LseekHoleSeeksToEOF,
"LseekEnxioCheck": LseekEnxioCheck,
"RenameOverwriteDestNoExist": RenameOverwriteDestNoExist, "RenameOverwriteDestNoExist": RenameOverwriteDestNoExist,
"RenameOverwriteDestExist": RenameOverwriteDestExist, "RenameOverwriteDestExist": RenameOverwriteDestExist,
"RenameOpenDir": RenameOpenDir, "RenameOpenDir": RenameOpenDir,
...@@ -720,3 +722,48 @@ func LseekHoleSeeksToEOF(t *testing.T, mnt string) { ...@@ -720,3 +722,48 @@ func LseekHoleSeeksToEOF(t *testing.T, mnt string) {
t.Errorf("got offset %d, want %d", off, len(content)) 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)
}
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment