Unverified Commit 7fd511f8 authored by Christian Brauner's avatar Christian Brauner
Browse files

nsfs: validate ioctls

Nsfs supports extensible and non-extensible ioctls. Validate both types
to prevent confusion.

Link: https://lore.kernel.org/r/20250219-work-nsfs-v1-1-21128d73c5e8@kernel.org


Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 2014c95a
Loading
Loading
Loading
Loading
+31 −1
Original line number Diff line number Diff line
@@ -152,19 +152,49 @@ static int copy_ns_info_to_user(const struct mnt_namespace *mnt_ns,
	return 0;
}

static bool nsfs_ioctl_valid(unsigned int cmd)
{
	switch (cmd) {
	case NS_GET_USERNS:
	case NS_GET_PARENT:
	case NS_GET_NSTYPE:
	case NS_GET_OWNER_UID:
	case NS_GET_MNTNS_ID:
	case NS_GET_PID_FROM_PIDNS:
	case NS_GET_TGID_FROM_PIDNS:
	case NS_GET_PID_IN_PIDNS:
	case NS_GET_TGID_IN_PIDNS:
		return (_IOC_TYPE(cmd) == _IOC_TYPE(cmd));
	}

	/* Extensible ioctls require some extra handling. */
	switch (_IOC_NR(cmd)) {
	case _IOC_NR(NS_MNT_GET_INFO):
	case _IOC_NR(NS_MNT_GET_NEXT):
	case _IOC_NR(NS_MNT_GET_PREV):
		return (_IOC_TYPE(cmd) == _IOC_TYPE(cmd));
	}

	return false;
}

static long ns_ioctl(struct file *filp, unsigned int ioctl,
			unsigned long arg)
{
	struct user_namespace *user_ns;
	struct pid_namespace *pid_ns;
	struct task_struct *tsk;
	struct ns_common *ns = get_proc_ns(file_inode(filp));
	struct ns_common *ns;
	struct mnt_namespace *mnt_ns;
	bool previous = false;
	uid_t __user *argp;
	uid_t uid;
	int ret;

	if (!nsfs_ioctl_valid(ioctl))
		return -ENOIOCTLCMD;

	ns = get_proc_ns(file_inode(filp));
	switch (ioctl) {
	case NS_GET_USERNS:
		return open_related_ns(ns, ns_get_owner);