Commit c536fc74 authored by David S. Miller's avatar David S. Miller
Browse files


Al Viro says:

====================
uaccess-related stuff in net/*

Assorted uaccess-related work in net/*.  First, there's
getting rid of compat_alloc_user_space() mess in MCAST_...
[gs]etsockopt() - no need to play with copying to/from temporary
object on userland stack, etc., when ->compat_[sg]etsockopt()
instances in question can easly do everything without that.
That's the first 13 patches.  Then there's a trivial bit in
net/batman-adv (completely unrelated to everything else) and
finally getting the atm compat ioctls into simpler shape.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f78cdbd7 0edecc02
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -123,7 +123,7 @@ extern int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf,int ifindex);
extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
		struct ip_msfilter __user *optval, int __user *optlen);
		struct ip_msfilter __user *optval, int __user *optlen);
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
		struct group_filter __user *optval, int __user *optlen);
			struct sockaddr_storage __user *p);
extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt,
extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt,
			  int dif, int sdif);
			  int dif, int sdif);
extern void ip_mc_init_dev(struct in_device *);
extern void ip_mc_init_dev(struct in_device *);
+23 −6
Original line number Original line Diff line number Diff line
@@ -67,11 +67,28 @@ int put_cmsg_compat(struct msghdr*, int, int, int, void *);
int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *,
int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *,
				     unsigned char *, int);
				     unsigned char *, int);


int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int,
struct compat_group_req {
			 int (*)(struct sock *, int, int, char __user *,
	__u32				 gr_interface;
				 unsigned int));
	struct __kernel_sockaddr_storage gr_group
int compat_mc_getsockopt(struct sock *, int, int, char __user *, int __user *,
		__aligned(4);
			 int (*)(struct sock *, int, int, char __user *,
} __packed;
				 int __user *));

struct compat_group_source_req {
	__u32				 gsr_interface;
	struct __kernel_sockaddr_storage gsr_group
		__aligned(4);
	struct __kernel_sockaddr_storage gsr_source
		__aligned(4);
} __packed;

struct compat_group_filter {
	__u32				 gf_interface;
	struct __kernel_sockaddr_storage gf_group
		__aligned(4);
	__u32				 gf_fmode;
	__u32				 gf_numsrc;
	struct __kernel_sockaddr_storage gf_slist[1]
		__aligned(4);
} __packed;


#endif /* NET_COMPAT_H */
#endif /* NET_COMPAT_H */
+3 −2
Original line number Original line Diff line number Diff line
@@ -1136,9 +1136,10 @@ struct group_filter;


int ip6_mc_source(int add, int omode, struct sock *sk,
int ip6_mc_source(int add, int omode, struct sock *sk,
		  struct group_source_req *pgsr);
		  struct group_source_req *pgsr);
int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf,
		  struct sockaddr_storage *list);
int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
		  struct group_filter __user *optval, int __user *optlen);
		  struct sockaddr_storage __user *p);


#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
int ac6_proc_init(struct net *net);
int ac6_proc_init(struct net *net);
+52 −44
Original line number Original line Diff line number Diff line
@@ -56,6 +56,8 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
	int error;
	int error;
	struct list_head *pos;
	struct list_head *pos;
	void __user *argp = (void __user *)arg;
	void __user *argp = (void __user *)arg;
	void __user *buf;
	int __user *len;


	vcc = ATM_SD(sock);
	vcc = ATM_SD(sock);
	switch (cmd) {
	switch (cmd) {
@@ -162,7 +164,49 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
	if (error != -ENOIOCTLCMD)
	if (error != -ENOIOCTLCMD)
		goto done;
		goto done;


	error = atm_dev_ioctl(cmd, argp, compat);
	if (cmd == ATM_GETNAMES) {
		if (IS_ENABLED(CONFIG_COMPAT) && compat) {
#ifdef CONFIG_COMPAT
			struct compat_atm_iobuf __user *ciobuf = argp;
			compat_uptr_t cbuf;
			len = &ciobuf->length;
			if (get_user(cbuf, &ciobuf->buffer))
				return -EFAULT;
			buf = compat_ptr(cbuf);
#endif
		} else {
			struct atm_iobuf __user *iobuf = argp;
			len = &iobuf->length;
			if (get_user(buf, &iobuf->buffer))
				return -EFAULT;
		}
		error = atm_getnames(buf, len);
	} else {
		int number;

		if (IS_ENABLED(CONFIG_COMPAT) && compat) {
#ifdef CONFIG_COMPAT
			struct compat_atmif_sioc __user *csioc = argp;
			compat_uptr_t carg;

			len = &csioc->length;
			if (get_user(carg, &csioc->arg))
				return -EFAULT;
			buf = compat_ptr(carg);
			if (get_user(number, &csioc->number))
				return -EFAULT;
#endif
		} else {
			struct atmif_sioc __user *sioc = argp;

			len = &sioc->length;
			if (get_user(buf, &sioc->arg))
				return -EFAULT;
			if (get_user(number, &sioc->number))
				return -EFAULT;
		}
		error = atm_dev_ioctl(cmd, buf, len, number, compat);
	}


done:
done:
	return error;
	return error;
@@ -230,61 +274,25 @@ static struct {
static int do_atm_iobuf(struct socket *sock, unsigned int cmd,
static int do_atm_iobuf(struct socket *sock, unsigned int cmd,
			unsigned long arg)
			unsigned long arg)
{
{
	struct atm_iobuf __user *iobuf;
	struct compat_atm_iobuf __user *iobuf32 = compat_ptr(arg);
	struct compat_atm_iobuf __user *iobuf32;
	u32 data;
	u32 data;
	void __user *datap;
	int len, err;

	iobuf = compat_alloc_user_space(sizeof(*iobuf));
	iobuf32 = compat_ptr(arg);


	if (get_user(len, &iobuf32->length) ||
	if (get_user(data, &iobuf32->buffer))
	    get_user(data, &iobuf32->buffer))
		return -EFAULT;
		return -EFAULT;
	datap = compat_ptr(data);
	if (put_user(len, &iobuf->length) ||
	    put_user(datap, &iobuf->buffer))
		return -EFAULT;

	err = do_vcc_ioctl(sock, cmd, (unsigned long) iobuf, 0);


	if (!err) {
	return atm_getnames(&iobuf32->length, compat_ptr(data));
		if (copy_in_user(&iobuf32->length, &iobuf->length,
				 sizeof(int)))
			err = -EFAULT;
	}

	return err;
}
}


static int do_atmif_sioc(struct socket *sock, unsigned int cmd,
static int do_atmif_sioc(struct socket *sock, unsigned int cmd,
			 unsigned long arg)
			 unsigned long arg)
{
{
	struct atmif_sioc __user *sioc;
	struct compat_atmif_sioc __user *sioc32 = compat_ptr(arg);
	struct compat_atmif_sioc __user *sioc32;
	int number;
	u32 data;
	u32 data;
	void __user *datap;
	int err;

	sioc = compat_alloc_user_space(sizeof(*sioc));
	sioc32 = compat_ptr(arg);


	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
	if (get_user(data, &sioc32->arg) || get_user(number, &sioc32->number))
	    get_user(data, &sioc32->arg))
		return -EFAULT;
	datap = compat_ptr(data);
	if (put_user(datap, &sioc->arg))
		return -EFAULT;
		return -EFAULT;

	return atm_dev_ioctl(cmd, compat_ptr(data), &sioc32->length, number, 0);
	err = do_vcc_ioctl(sock, cmd, (unsigned long) sioc, 0);

	if (!err) {
		if (copy_in_user(&sioc32->length, &sioc->length,
				 sizeof(int)))
			err = -EFAULT;
	}
	return err;
}
}


static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
+34 −74
Original line number Original line Diff line number Diff line
@@ -193,33 +193,13 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg,
	return error ? -EFAULT : 0;
	return error ? -EFAULT : 0;
}
}


int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
int atm_getnames(void __user *buf, int __user *iobuf_len)
{
{
	void __user *buf;
	int error, len, size = 0;
	int error, len, number, size = 0;
	struct atm_dev *dev;
	struct atm_dev *dev;
	struct list_head *p;
	struct list_head *p;
	int *tmp_buf, *tmp_p;
	int *tmp_buf, *tmp_p;
	int __user *sioc_len;
	int __user *iobuf_len;


	switch (cmd) {
	case ATM_GETNAMES:
		if (IS_ENABLED(CONFIG_COMPAT) && compat) {
#ifdef CONFIG_COMPAT
			struct compat_atm_iobuf __user *ciobuf = arg;
			compat_uptr_t cbuf;
			iobuf_len = &ciobuf->length;
			if (get_user(cbuf, &ciobuf->buffer))
				return -EFAULT;
			buf = compat_ptr(cbuf);
#endif
		} else {
			struct atm_iobuf __user *iobuf = arg;
			iobuf_len = &iobuf->length;
			if (get_user(buf, &iobuf->buffer))
				return -EFAULT;
		}
	if (get_user(len, iobuf_len))
	if (get_user(len, iobuf_len))
		return -EFAULT;
		return -EFAULT;
	mutex_lock(&atm_dev_mutex);
	mutex_lock(&atm_dev_mutex);
@@ -245,36 +225,16 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
		? -EFAULT : 0;
		? -EFAULT : 0;
	kfree(tmp_buf);
	kfree(tmp_buf);
	return error;
	return error;
	default:
		break;
}
}


	if (IS_ENABLED(CONFIG_COMPAT) && compat) {
int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len,
#ifdef CONFIG_COMPAT
		  int number, int compat)
		struct compat_atmif_sioc __user *csioc = arg;
{
		compat_uptr_t carg;
	int error, len, size = 0;

	struct atm_dev *dev;
		sioc_len = &csioc->length;
		if (get_user(carg, &csioc->arg))
			return -EFAULT;
		buf = compat_ptr(carg);

		if (get_user(len, &csioc->length))
			return -EFAULT;
		if (get_user(number, &csioc->number))
			return -EFAULT;
#endif
	} else {
		struct atmif_sioc __user *sioc = arg;


		sioc_len = &sioc->length;
	if (get_user(len, sioc_len))
		if (get_user(buf, &sioc->arg))
		return -EFAULT;
		return -EFAULT;
		if (get_user(len, &sioc->length))
			return -EFAULT;
		if (get_user(number, &sioc->number))
			return -EFAULT;
	}


	dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d",
	dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d",
				      number);
				      number);
Loading