criu: validate non-regular descriptor files - #5402
Conversation
When restore opens `descriptors.json` from the checkpoint image, a FIFO at this path may block the read indefinitely, so repeated restore attempts can exhaust caller threads in container runtimes. To fix this, we should open this file through the pre-opened image directory with `O_PATH`, verify the inode is a regular file, and reopen that handle for reading. This patch also rejects symlinks and other special files, and limits the read to 1 MiB to prevent unbounded allocations. Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
| // type check, so the checked inode is the one that is read). | ||
| func openRegularFileAt(dir *os.File, name string) (*os.File, error) { | ||
| path := filepath.Join(dir.Name(), name) | ||
| handle, err := utils.Openat(dir, name, unix.O_PATH|unix.O_NOFOLLOW, 0) |
There was a problem hiding this comment.
nit: add O_PATH?
May also add O_CLOEXEC to be explicit, but it's added by utils.Openat anyway
| path := filepath.Join(dir.Name(), name) | ||
| handle, err := utils.Openat(dir, name, unix.O_PATH|unix.O_NOFOLLOW, 0) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("open %s: %w", path, err) |
There was a problem hiding this comment.
nit: no need to wrap the error as it already comes as os.PathError with both "open" and path specified.
|
|
||
| info, err := handle.Stat() | ||
| if err != nil { | ||
| return nil, fmt.Errorf("stat %s: %w", path, err) |
There was a problem hiding this comment.
same here: the error from stat is os.PathError telling both the op (stat) and the path.
|
|
||
| info, err := f.Stat() | ||
| if err != nil { | ||
| return nil, fmt.Errorf("stat %s: %w", path, err) |
| } | ||
| defer f.Close() | ||
|
|
||
| info, err := f.Stat() |
There was a problem hiding this comment.
I slightly dislike that you're doing two stat calls on the same file -- once to check if it's a regular file, then to check the size. Can probably combine those.
|
So, we have the same issue when reading say |
When restore opens
descriptors.jsonfrom the checkpoint image, a FIFO at this path may block the read indefinitely, so repeated restore attempts can exhaust caller threads in container runtimes. To fix this, we should open this file through the pre-opened image directory withO_PATH, verify the inode is a regular file, and reopen that handle for reading. This patch also rejects symlinks and other special files, and limits the read to 1 MiB to prevent unbounded allocations.