Skip to content

Commit

Permalink
ipmr: Create a wrapper that understands ioctl
Browse files Browse the repository at this point in the history
Create a wrapper for ipmr that knows how to handle ioctl. The goal is to
move ioctl callback functions from accessing userspace, such as
put_user()/from_user(), from the function itself.

This function knows how to copy the proper structures to kernel space
memory before ioctl being called. This function also copy the buffer
that came from the function ioctl back to user space. That way, the
ioctl function does not need to deal with userspace memory and became
more flexible.

Signed-off-by: Breno Leitao <leitao@debian.org>
  • Loading branch information
leitao committed Apr 18, 2023
1 parent 464e76b commit 659a76d
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/mroute.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ int ip_mroute_getsockopt(struct sock *, int, sockptr_t, sockptr_t);
int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg);
int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
int ip_mr_init(void);
int sock_skprot_ioctl_ipmr(struct sock *sk, unsigned int cmd, unsigned long arg);
bool ipmr_rule_default(const struct fib_rule *rule);
#else
static inline int ip_mroute_setsockopt(struct sock *sock, int optname,
Expand Down
37 changes: 37 additions & 0 deletions net/ipv4/ipmr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,43 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
return 0;
}

int sock_skprot_ioctl_ipmr(struct sock *sk, unsigned int cmd,
unsigned long arg)
{
void __user *ptr = (void __user *)arg;
int ret;

/* This is a special case where ipmr_ioctl will be called */
switch (cmd) {
case SIOCGETVIFCNT: {
struct sioc_vif_req vr;

if (copy_from_user(&vr, ptr, sizeof(vr)))
return -EFAULT;
ret = ipmr_ioctl(sk, cmd, &vr);
if (ret)
return ret;
if (copy_to_user(ptr, &vr, sizeof(vr)))
return -EFAULT;
return 0;
}
case SIOCGETSGCNT: {
struct sioc_sg_req sr;

if (copy_from_user(&sr, ptr, sizeof(sr)))
return -EFAULT;
ret = ipmr_ioctl(sk, cmd, &sr);
if (ret)
return ret;
if (copy_to_user(ptr, &sr, sizeof(sr)))
return -EFAULT;
return 0;
}
default:
return -ENOIOCTLCMD;
}
}

/* The IP multicast ioctl support routines. */
int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
{
Expand Down

0 comments on commit 659a76d

Please sign in to comment.