Commit c2f12630 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David S. Miller
Browse files

netfilter: switch nf_setsockopt to sockptr_t



Pass a sockptr_t to prepare for set_fs-less handling of the kernel
pointer from bpf-cgroup.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ab214d1b
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/static_key.h>
#include <linux/netfilter_defs.h>
#include <linux/netdevice.h>
#include <linux/sockptr.h>
#include <net/net_namespace.h>

static inline int NF_DROP_GETERR(int verdict)
@@ -163,7 +164,8 @@ struct nf_sockopt_ops {
	/* Non-inclusive ranges: use 0/0/NULL to never get called. */
	int set_optmin;
	int set_optmax;
	int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len);
	int (*set)(struct sock *sk, int optval, sockptr_t arg,
		   unsigned int len);
	int get_optmin;
	int get_optmax;
	int (*get)(struct sock *sk, int optval, void __user *user, int *len);
@@ -338,7 +340,7 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
}

/* Call setsockopt() */
int nf_setsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt,
int nf_setsockopt(struct sock *sk, u_int8_t pf, int optval, sockptr_t opt,
		  unsigned int len);
int nf_getsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt,
		  int *len);
+17 −20
Original line number Diff line number Diff line
@@ -1063,14 +1063,13 @@ free_counterstmp:
}

/* replace the table */
static int do_replace(struct net *net, const void __user *user,
		      unsigned int len)
static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
{
	int ret, countersize;
	struct ebt_table_info *newinfo;
	struct ebt_replace tmp;

	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
	if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
		return -EFAULT;

	if (len != sizeof(tmp) + tmp.entries_size)
@@ -1286,12 +1285,11 @@ free_tmp:
	return ret;
}

static int update_counters(struct net *net, const void __user *user,
			    unsigned int len)
static int update_counters(struct net *net, sockptr_t arg, unsigned int len)
{
	struct ebt_replace hlp;

	if (copy_from_user(&hlp, user, sizeof(hlp)))
	if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
		return -EFAULT;

	if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
@@ -2079,7 +2077,7 @@ static int compat_copy_entries(unsigned char *data, unsigned int size_user,


static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
					    void __user *user, unsigned int len)
					     sockptr_t arg, unsigned int len)
{
	struct compat_ebt_replace tmp;
	int i;
@@ -2087,7 +2085,7 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
	if (len < sizeof(tmp))
		return -EINVAL;

	if (copy_from_user(&tmp, user, sizeof(tmp)))
	if (copy_from_sockptr(&tmp, arg, sizeof(tmp)))
		return -EFAULT;

	if (len != sizeof(tmp) + tmp.entries_size)
@@ -2114,8 +2112,7 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
	return 0;
}

static int compat_do_replace(struct net *net, void __user *user,
			     unsigned int len)
static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
{
	int ret, i, countersize, size64;
	struct ebt_table_info *newinfo;
@@ -2123,10 +2120,10 @@ static int compat_do_replace(struct net *net, void __user *user,
	struct ebt_entries_buf_state state;
	void *entries_tmp;

	ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
	ret = compat_copy_ebt_replace_from_user(&tmp, arg, len);
	if (ret) {
		/* try real handler in case userland supplied needed padding */
		if (ret == -EINVAL && do_replace(net, user, len) == 0)
		if (ret == -EINVAL && do_replace(net, arg, len) == 0)
			ret = 0;
		return ret;
	}
@@ -2217,17 +2214,17 @@ out_unlock:
	goto free_entries;
}

static int compat_update_counters(struct net *net, void __user *user,
static int compat_update_counters(struct net *net, sockptr_t arg,
				  unsigned int len)
{
	struct compat_ebt_replace hlp;

	if (copy_from_user(&hlp, user, sizeof(hlp)))
	if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
		return -EFAULT;

	/* try real handler in case userland supplied needed padding */
	if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
		return update_counters(net, user, len);
		return update_counters(net, arg, len);

	return do_update_counters(net, hlp.name, compat_ptr(hlp.counters),
				  hlp.num_counters, len);
@@ -2368,7 +2365,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
	return ret;
}

static int do_ebt_set_ctl(struct sock *sk, int cmd, void __user *user,
static int do_ebt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
		unsigned int len)
{
	struct net *net = sock_net(sk);
@@ -2381,18 +2378,18 @@ static int do_ebt_set_ctl(struct sock *sk, int cmd, void __user *user,
	case EBT_SO_SET_ENTRIES:
#ifdef CONFIG_COMPAT
		if (in_compat_syscall())
			ret = compat_do_replace(net, user, len);
			ret = compat_do_replace(net, arg, len);
		else
#endif
			ret = do_replace(net, user, len);
			ret = do_replace(net, arg, len);
		break;
	case EBT_SO_SET_COUNTERS:
#ifdef CONFIG_COMPAT
		if (in_compat_syscall())
			ret = compat_update_counters(net, user, len);
			ret = compat_update_counters(net, arg, len);
		else
#endif
			ret = update_counters(net, user, len);
			ret = update_counters(net, arg, len);
		break;
	default:
		ret = -EINVAL;
+2 −1
Original line number Diff line number Diff line
@@ -1332,7 +1332,8 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char __use
	/* we need to exclude all possible ENOPROTOOPTs except default case */
	if (err == -ENOPROTOOPT && optname != DSO_LINKINFO &&
	    optname != DSO_STREAM && optname != DSO_SEQPACKET)
		err = nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);
		err = nf_setsockopt(sk, PF_DECnet, optname,
				    USER_SOCKPTR(optval), optlen);
#endif

	return err;
+2 −1
Original line number Diff line number Diff line
@@ -1422,7 +1422,8 @@ int ip_setsockopt(struct sock *sk, int level,
			optname != IP_IPSEC_POLICY &&
			optname != IP_XFRM_POLICY &&
			!ip_mroute_opt(optname))
		err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
		err = nf_setsockopt(sk, PF_INET, optname, USER_SOCKPTR(optval),
				    optlen);
#endif
	return err;
}
+14 −14
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only

/*
 * Packet matching code for ARP packets.
 *
@@ -947,8 +947,7 @@ static int __do_replace(struct net *net, const char *name,
	return ret;
}

static int do_replace(struct net *net, const void __user *user,
		      unsigned int len)
static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
{
	int ret;
	struct arpt_replace tmp;
@@ -956,7 +955,7 @@ static int do_replace(struct net *net, const void __user *user,
	void *loc_cpu_entry;
	struct arpt_entry *iter;

	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
	if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
		return -EFAULT;

	/* overflow check */
@@ -972,8 +971,8 @@ static int do_replace(struct net *net, const void __user *user,
		return -ENOMEM;

	loc_cpu_entry = newinfo->entries;
	if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
			   tmp.size) != 0) {
	sockptr_advance(arg, sizeof(tmp));
	if (copy_from_sockptr(loc_cpu_entry, arg, tmp.size) != 0) {
		ret = -EFAULT;
		goto free_newinfo;
	}
@@ -1244,8 +1243,7 @@ out_unlock:
	return ret;
}

static int compat_do_replace(struct net *net, void __user *user,
			     unsigned int len)
static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
{
	int ret;
	struct compat_arpt_replace tmp;
@@ -1253,7 +1251,7 @@ static int compat_do_replace(struct net *net, void __user *user,
	void *loc_cpu_entry;
	struct arpt_entry *iter;

	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
	if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
		return -EFAULT;

	/* overflow check */
@@ -1269,7 +1267,8 @@ static int compat_do_replace(struct net *net, void __user *user,
		return -ENOMEM;

	loc_cpu_entry = newinfo->entries;
	if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), tmp.size) != 0) {
	sockptr_advance(arg, sizeof(tmp));
	if (copy_from_sockptr(loc_cpu_entry, arg, tmp.size) != 0) {
		ret = -EFAULT;
		goto free_newinfo;
	}
@@ -1401,7 +1400,8 @@ static int compat_get_entries(struct net *net,
}
#endif

static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
static int do_arpt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
		unsigned int len)
{
	int ret;

@@ -1412,14 +1412,14 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned
	case ARPT_SO_SET_REPLACE:
#ifdef CONFIG_COMPAT
		if (in_compat_syscall())
			ret = compat_do_replace(sock_net(sk), user, len);
			ret = compat_do_replace(sock_net(sk), arg, len);
		else
#endif
			ret = do_replace(sock_net(sk), user, len);
			ret = do_replace(sock_net(sk), arg, len);
		break;

	case ARPT_SO_SET_ADD_COUNTERS:
		ret = do_add_counters(sock_net(sk), USER_SOCKPTR(user), len);
		ret = do_add_counters(sock_net(sk), arg, len);
		break;

	default:
Loading