mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Handle NUL-only paths in exec
The path in execve(2), interpreter script, and ELF interpreter may all be no more than a NUL-byte. Handle each of those cases. PiperOrigin-RevId: 203155745 Change-Id: I1c8b1b387924b23b2cf942341dfc76c9003da959
This commit is contained in:
@@ -405,6 +405,10 @@ func loadParsedELF(ctx context.Context, m *mm.MemoryManager, f *fs.File, info el
|
||||
}
|
||||
|
||||
case elf.PT_INTERP:
|
||||
if phdr.Filesz < 2 {
|
||||
ctx.Infof("PT_INTERP path too small: %v", phdr.Filesz)
|
||||
return loadedELF{}, syserror.ENOEXEC
|
||||
}
|
||||
if phdr.Filesz > syscall.PathMax {
|
||||
ctx.Infof("PT_INTERP path too big: %v", phdr.Filesz)
|
||||
return loadedELF{}, syserror.ENOEXEC
|
||||
@@ -423,8 +427,26 @@ func loadParsedELF(ctx context.Context, m *mm.MemoryManager, f *fs.File, info el
|
||||
return loadedELF{}, syserror.ENOEXEC
|
||||
}
|
||||
|
||||
// Strip NUL-terminator from string.
|
||||
interpreter = string(path[:len(path)-1])
|
||||
// Strip NUL-terminator and everything beyond from
|
||||
// string. Note that there may be a NUL-terminator
|
||||
// before len(path)-1.
|
||||
interpreter = string(path[:bytes.IndexByte(path, '\x00')])
|
||||
if interpreter == "" {
|
||||
// Linux actually attempts to open_exec("\0").
|
||||
// open_exec -> do_open_execat fails to check
|
||||
// that name != '\0' before calling
|
||||
// do_filp_open, which thus opens the working
|
||||
// directory. do_open_execat returns EACCES
|
||||
// because the directory is not a regular file.
|
||||
//
|
||||
// We bypass that nonsense and simply
|
||||
// short-circuit with EACCES. Those this does
|
||||
// mean that there may be some edge cases where
|
||||
// the open path would return a different
|
||||
// error.
|
||||
ctx.Infof("PT_INTERP path is empty: %v", path)
|
||||
return loadedELF{}, syserror.EACCES
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,11 @@ func parseInterpreterScript(ctx context.Context, filename string, f *fs.File, ar
|
||||
}
|
||||
}
|
||||
|
||||
if string(interp) == "" {
|
||||
ctx.Infof("Interpreter script contains no interpreter: %v", line)
|
||||
return "", []string{}, syserror.ENOEXEC
|
||||
}
|
||||
|
||||
// Build the new argument list:
|
||||
//
|
||||
// 1. The interpreter.
|
||||
|
||||
@@ -55,6 +55,11 @@ func readFull(ctx context.Context, f *fs.File, dst usermem.IOSequence, offset in
|
||||
//
|
||||
// name must be a readable, executable, regular file.
|
||||
func openPath(ctx context.Context, mm *fs.MountNamespace, root, wd *fs.Dirent, maxTraversals uint, name string) (*fs.Dirent, *fs.File, error) {
|
||||
if name == "" {
|
||||
ctx.Infof("cannot open empty name")
|
||||
return nil, nil, syserror.ENOENT
|
||||
}
|
||||
|
||||
d, err := mm.FindInode(ctx, root, wd, name, maxTraversals)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
Reference in New Issue
Block a user