Unverified Commit 091ee63e authored by Christian Brauner's avatar Christian Brauner
Browse files

pidfs: improve ioctl handling

Pidfs supports extensible and non-extensible ioctls. The extensible
ioctls need to check for the ioctl number itself not just the ioctl
command otherwise both backward- and forward compatibility are broken.

The pidfs ioctl handler also needs to look at the type of the ioctl
command to guard against cases where "[...] a daemon receives some
random file descriptor from a (potentially less privileged) client and
expects the FD to be of some specific type, it might call ioctl() on
this FD with some type-specific command and expect the call to fail if
the FD is of the wrong type; but due to the missing type check, the
kernel instead performs some action that userspace didn't expect."
(cf. [1]]

Link: https://lore.kernel.org/r/20250204-work-pidfs-ioctl-v1-1-04987d239575@kernel.org
Link: https://lore.kernel.org/r/CAG48ez2K9A5GwtgqO31u9ZL292we8ZwAA=TJwwEv7wRuJ3j4Lw@mail.gmail.com

 [1]
Fixes: 8ce35281 ("pidfs: check for valid ioctl commands")
Acked-by: default avatarLuca Boccassi <luca.boccassi@gmail.com>
Reported-by: default avatarJann Horn <jannh@google.com>
Cc: stable@vger.kernel.org # v6.13; please backport with 8ce35281 ("pidfs: check for valid ioctl commands")
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent ec6164ad
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -287,7 +287,6 @@ static bool pidfs_ioctl_valid(unsigned int cmd)
	switch (cmd) {
	case FS_IOC_GETVERSION:
	case PIDFD_GET_CGROUP_NAMESPACE:
	case PIDFD_GET_INFO:
	case PIDFD_GET_IPC_NAMESPACE:
	case PIDFD_GET_MNT_NAMESPACE:
	case PIDFD_GET_NET_NAMESPACE:
@@ -300,6 +299,17 @@ static bool pidfs_ioctl_valid(unsigned int cmd)
		return true;
	}

	/* Extensible ioctls require some more careful checks. */
	switch (_IOC_NR(cmd)) {
	case _IOC_NR(PIDFD_GET_INFO):
		/*
		 * Try to prevent performing a pidfd ioctl when someone
		 * erronously mistook the file descriptor for a pidfd.
		 * This is not perfect but will catch most cases.
		 */
		return (_IOC_TYPE(cmd) == _IOC_TYPE(PIDFD_GET_INFO));
	}

	return false;
}