singularity
singularity copied to clipboard
Use openat when possible
To prevent the possibility of any ToCToE attacks, we should use openat()
when looking at a directory and later opening a file contained within that directory. This will require a bit of investigation into the code to find the locations where this pattern is applicable. As a starting point, here is every reference to *.Open()
that exists in our codebase (excluding vendor/
):
internal/app/singularity/oci_create_linux.go: fb, err := os.Open(configJSON)
internal/app/singularity/oci_update_linux.go: f, err := os.Open(args.FromFile)
internal/app/singularity/plugin_compile_linux.go: fp, err := os.Open(objInput.Fname)
internal/app/singularity/plugin_compile_linux.go: fp, err := os.Open(manifestInput.Fname)
internal/pkg/util/fs/files/passwd.go: passwdFile, err := os.Open(path)
internal/pkg/util/fs/files/group.go: groupFile, err := os.Open(path)
internal/pkg/instance/instance_linux.go: r, err := os.Open(file)
internal/pkg/plugin/load.go: pluginPointer, err := plugin.Open(path)
internal/pkg/plugin/binary.go: return os.Open(m.configName())
internal/pkg/plugin/binary.go: fh, err := os.Open(filename)
internal/pkg/test/privilege_darwin.go: f, err := os.Open(fmt.Sprintf("/proc/%v/status", pid))
internal/pkg/test/privilege_linux.go: f, err := os.Open(fmt.Sprintf("/proc/%v/status", pid))
internal/pkg/runtime/engines/config/parser.go: c, err = os.Open(filepath)
internal/pkg/runtime/engines/singularity/container_linux.go: f, err := syscall.Open("/proc/"+strconv.Itoa(pid)+"/ns/net", os.O_RDONLY, 0)
internal/pkg/runtime/engines/singularity/container_linux.go: r, err := os.Open(resolvConf)
internal/pkg/runtime/engines/singularity/rpc/server/server_linux.go: oldroot, err := os.Open("/")
internal/pkg/runtime/engines/singularity/prepare_linux.go: f, err := os.Open(src)
internal/pkg/runtime/engines/singularity/prepare_linux.go: f, err := os.Open(src)
internal/pkg/runtime/engines/singularity/prepare_linux.go: f, err := os.Open(path)
internal/pkg/runtime/engines/oci/create_linux.go: f, err := os.Open(fmt.Sprintf("/proc/%d/cgroup", pid))
internal/pkg/runtime/engines/oci/prepare_linux.go: master, slave, err = pty.Open()
internal/pkg/build/assemblers/assembler_sif.go: fp, err := os.Open(parinput.Fname)
internal/pkg/build/build.go: defFile, err := os.Open(spec)
internal/pkg/build/build.go: defFile, err := os.Open(spec)
internal/pkg/build/sources/conveyorPacker_arch_test.go: defFile, err := os.Open(archDef)
internal/pkg/build/sources/conveyorPacker_arch_test.go: defFile, err := os.Open(archDef)
internal/pkg/build/sources/conveyorPacker_oci.go: f, err := os.Open(src)
internal/pkg/build/sources/conveyorPacker_busybox_test.go: defFile, err := os.Open(busyBoxDef)
internal/pkg/build/sources/conveyorPacker_busybox_test.go: defFile, err := os.Open(busyBoxDef)
internal/pkg/build/sources/conveyorPacker_yum_test.go: defFile, err := os.Open(yumDef)
internal/pkg/build/sources/conveyorPacker_yum_test.go: defFile, err := os.Open(yumDef)
internal/pkg/build/sources/conveyorPacker_zypper_test.go: defFile, err := os.Open(zyppDef)
internal/pkg/build/sources/conveyorPacker_zypper_test.go: defFile, err := os.Open(zyppDef)
internal/pkg/build/sources/conveyorPacker_scratch_test.go: defFile, err := os.Open(scratchDef)
internal/pkg/build/sources/conveyorPacker_scratch_test.go: defFile, err := os.Open(scratchDef)
internal/pkg/build/metadata.go: jsonFile, err := os.Open(filepath.Join(b.Rootfs(), "/.singularity.d/labels.json"))
internal/pkg/cgroups/cgroups_linux_test.go: file, err := os.Open(path)
internal/pkg/cgroups/cgroups_linux_test.go: file, err := os.Open(fmt.Sprintf("/proc/%d/status", manager.Pid))
internal/pkg/cgroups/cgroups_linux_test.go: file, err = os.Open(fmt.Sprintf("/proc/%d/status", manager.Pid))
internal/pkg/security/seccomp/seccomp_linux.go: file, err := os.Open(profile)
internal/pkg/syecl/syecl_test.go: s, err := os.Open(src)
internal/pkg/syecl/syecl.go: fp, err := os.Open(cpath)
pkg/util/fs/proc/proc.go: p, err := os.Open("/proc/filesystems")
pkg/util/fs/proc/proc.go: p, err := os.Open(path)
pkg/util/fs/proc/proc.go: p, err := os.Open("/proc/self/mountinfo")
pkg/util/fs/proc/proc.go: r, err := os.Open(filepath.Join(path, "status"))
pkg/util/fs/proc/proc.go: r, err := os.Open(path)
pkg/util/fs/lock/lock.go: fd, err = syscall.Open(path, os.O_RDONLY, 0)
pkg/util/nvidia/paths.go: file, err := os.Open(nvliblistPath)
pkg/util/nvidia/paths.go: self, err := elf.Open("/proc/self/exe")
pkg/util/nvidia/paths.go: elib, err := elf.Open(libPath)
pkg/util/loop/loop_linux.go: if loopFd, err = syscall.Open(path, mode, 0600); err != nil {
pkg/util/loop/loop_linux.go: loop, err := os.Open(path)
pkg/util/loop/loop_linux_test.go: f, err := os.Open("/etc/passwd")
pkg/util/namespaces/setns_linux.go: f, err := os.Open(path)
pkg/client/library/util.go: file, err := os.Open(filePath)
pkg/client/library/pull_test.go: inFile, err := os.Open(m.testFile)
pkg/client/library/push.go: f, err := os.Open(filePath)
pkg/sypgp/sypgp.go: f, err := os.Open(SecretPath())
pkg/sypgp/sypgp.go: f, err := os.Open(PublicPath())
pkg/sypgp/sypgp.go: f, err := os.Open(path)
pkg/build/legacy/parser/deffile.go: defFile, err := os.Open(source)
pkg/build/legacy/parser/deffile_test.go: r, err := os.Open(deffile)
pkg/build/legacy/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/legacy/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/parser/deffile.go: defFile, err := os.Open(source)
pkg/build/types/parser/deffile_test.go: r, err := os.Open(deffile)
pkg/build/types/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/definition_test.go: f, err := os.Open(singularityJSON)
I imagine that we'll be able to ignore a decent chunk of those, such as the pieces which are pertinent to image building. However, for the rest I think we'll want to go through and look for times where we open a file having first performed some type of validation of its' directory existing (or similar). Then we'll be able to come up with a list of places we can use Openat()
and go on from there.
Slimming down the list, ignoring anything that only pertains to image building:
internal/app/singularity/oci_create_linux.go: fb, err := os.Open(configJSON)
internal/app/singularity/oci_update_linux.go: f, err := os.Open(args.FromFile)
internal/app/singularity/plugin_compile_linux.go: fp, err := os.Open(objInput.Fname)
internal/app/singularity/plugin_compile_linux.go: fp, err := os.Open(manifestInput.Fname)
internal/pkg/util/fs/files/passwd.go: passwdFile, err := os.Open(path)
internal/pkg/util/fs/files/group.go: groupFile, err := os.Open(path)
internal/pkg/instance/instance_linux.go: r, err := os.Open(file)
internal/pkg/plugin/load.go: pluginPointer, err := plugin.Open(path)
internal/pkg/plugin/binary.go: return os.Open(m.configName())
internal/pkg/plugin/binary.go: fh, err := os.Open(filename)
internal/pkg/test/privilege_darwin.go: f, err := os.Open(fmt.Sprintf("/proc/%v/status", pid))
internal/pkg/test/privilege_linux.go: f, err := os.Open(fmt.Sprintf("/proc/%v/status", pid))
internal/pkg/runtime/engines/config/parser.go: c, err = os.Open(filepath)
internal/pkg/runtime/engines/singularity/container_linux.go: f, err := syscall.Open("/proc/"+strconv.Itoa(pid)+"/ns/net", os.O_RDONLY, 0)
internal/pkg/runtime/engines/singularity/container_linux.go: r, err := os.Open(resolvConf)
internal/pkg/runtime/engines/singularity/rpc/server/server_linux.go: oldroot, err := os.Open("/")
internal/pkg/runtime/engines/singularity/prepare_linux.go: f, err := os.Open(src)
internal/pkg/runtime/engines/singularity/prepare_linux.go: f, err := os.Open(src)
internal/pkg/runtime/engines/singularity/prepare_linux.go: f, err := os.Open(path)
internal/pkg/runtime/engines/oci/create_linux.go: f, err := os.Open(fmt.Sprintf("/proc/%d/cgroup", pid))
internal/pkg/runtime/engines/oci/prepare_linux.go: master, slave, err = pty.Open()
internal/pkg/cgroups/cgroups_linux_test.go: file, err := os.Open(path)
internal/pkg/cgroups/cgroups_linux_test.go: file, err := os.Open(fmt.Sprintf("/proc/%d/status", manager.Pid))
internal/pkg/cgroups/cgroups_linux_test.go: file, err = os.Open(fmt.Sprintf("/proc/%d/status", manager.Pid))
internal/pkg/security/seccomp/seccomp_linux.go: file, err := os.Open(profile)
internal/pkg/syecl/syecl_test.go: s, err := os.Open(src)
internal/pkg/syecl/syecl.go: fp, err := os.Open(cpath)
pkg/util/fs/proc/proc.go: p, err := os.Open("/proc/filesystems")
pkg/util/fs/proc/proc.go: p, err := os.Open(path)
pkg/util/fs/proc/proc.go: p, err := os.Open("/proc/self/mountinfo")
pkg/util/fs/proc/proc.go: r, err := os.Open(filepath.Join(path, "status"))
pkg/util/fs/proc/proc.go: r, err := os.Open(path)
pkg/util/fs/lock/lock.go: fd, err = syscall.Open(path, os.O_RDONLY, 0)
pkg/util/nvidia/paths.go: file, err := os.Open(nvliblistPath)
pkg/util/nvidia/paths.go: self, err := elf.Open("/proc/self/exe")
pkg/util/nvidia/paths.go: elib, err := elf.Open(libPath)
pkg/util/loop/loop_linux.go: if loopFd, err = syscall.Open(path, mode, 0600); err != nil {
pkg/util/loop/loop_linux.go: loop, err := os.Open(path)
pkg/util/loop/loop_linux_test.go: f, err := os.Open("/etc/passwd")
pkg/util/namespaces/setns_linux.go: f, err := os.Open(path)
pkg/client/library/util.go: file, err := os.Open(filePath)
pkg/client/library/pull_test.go: inFile, err := os.Open(m.testFile)
pkg/client/library/push.go: f, err := os.Open(filePath)
pkg/sypgp/sypgp.go: f, err := os.Open(SecretPath())
pkg/sypgp/sypgp.go: f, err := os.Open(PublicPath())
pkg/sypgp/sypgp.go: f, err := os.Open(path)
These were removed:
internal/pkg/build/assemblers/assembler_sif.go: fp, err := os.Open(parinput.Fname)
internal/pkg/build/build.go: defFile, err := os.Open(spec)
internal/pkg/build/build.go: defFile, err := os.Open(spec)
internal/pkg/build/sources/conveyorPacker_arch_test.go: defFile, err := os.Open(archDef)
internal/pkg/build/sources/conveyorPacker_arch_test.go: defFile, err := os.Open(archDef)
internal/pkg/build/sources/conveyorPacker_oci.go: f, err := os.Open(src)
internal/pkg/build/sources/conveyorPacker_busybox_test.go: defFile, err := os.Open(busyBoxDef)
internal/pkg/build/sources/conveyorPacker_busybox_test.go: defFile, err := os.Open(busyBoxDef)
internal/pkg/build/sources/conveyorPacker_yum_test.go: defFile, err := os.Open(yumDef)
internal/pkg/build/sources/conveyorPacker_yum_test.go: defFile, err := os.Open(yumDef)
internal/pkg/build/sources/conveyorPacker_zypper_test.go: defFile, err := os.Open(zyppDef)
internal/pkg/build/sources/conveyorPacker_zypper_test.go: defFile, err := os.Open(zyppDef)
internal/pkg/build/sources/conveyorPacker_scratch_test.go: defFile, err := os.Open(scratchDef)
internal/pkg/build/sources/conveyorPacker_scratch_test.go: defFile, err := os.Open(scratchDef)
internal/pkg/build/metadata.go: jsonFile, err := os.Open(filepath.Join(b.Rootfs(), "/.singularity.d/labels.json"))
pkg/build/legacy/parser/deffile.go: defFile, err := os.Open(source)
pkg/build/legacy/parser/deffile_test.go: r, err := os.Open(deffile)
pkg/build/legacy/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/legacy/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/parser/deffile.go: defFile, err := os.Open(source)
pkg/build/types/parser/deffile_test.go: r, err := os.Open(deffile)
pkg/build/types/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/parser/deffile_test.go: defFile, err := os.Open(tt.defPath)
pkg/build/types/definition_test.go: f, err := os.Open(singularityJSON)
It still might not be a bad idea to apply the same checking/updating process to those which we remove, but it's more important to first improve the pieces of our code base which will potentially be run in a suid context.
This seems like something that would be a good idea to add as a linter to our CI. What do you think?
Hello,
This is a templated response that is being sent out to all open issues. We are working hard on 'rebuilding' the Singularity community, and a major task on the agenda is finding out what issues are still outstanding.
Please consider the following:
- Is this issue a duplicate, or has it been fixed/implemented since being added?
- Is the issue still relevant to the current state of Singularity's functionality?
- Would you like to continue discussing this issue or feature request?
Thanks, Carter
This issue has been automatically marked as stale because it has not had activity in over 60 days. It will be closed in 7 days if no further activity occurs. Thank you for your contributions.
@bauerm97 Still getting this problem ? Have this been solved already ? If yes, what work around have you followed and applied ?
We're looking into the issue carefully, soon will bring to community and discuss ways to better solve as well address this. Thankyou for keeping the interest in the subject.
Copied to https://github.com/apptainer/apptainer/issues/791