Continue converting the proto-layer getsockopt callbacks to the sockopt_t interface, switching do_raw_getsockopt() and its raw_geticmpfilter() helper to take a sockopt_t.
The thin raw_getsockopt() wrapper keeps its __user signature for now: it builds a user-backed sockopt_t with sockopt_init_user(), calls the helper, and writes the returned length back to optlen. The helper uses copy_to_iter() instead of copy_to_user(). No functional change. Signed-off-by: Breno Leitao <[email protected]> --- net/ipv4/raw.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e9fbab6ad9146..2aebaf8297e04 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -809,23 +809,18 @@ static int raw_seticmpfilter(struct sock *sk, sockptr_t optval, int optlen) return 0; } -static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *optlen) +static int raw_geticmpfilter(struct sock *sk, sockopt_t *opt) { - int len, ret = -EFAULT; + int len = opt->optlen; - if (get_user(len, optlen)) - goto out; - ret = -EINVAL; if (len < 0) - goto out; + return -EINVAL; if (len > sizeof(struct icmp_filter)) len = sizeof(struct icmp_filter); - ret = -EFAULT; - if (put_user(len, optlen) || - copy_to_user(optval, &raw_sk(sk)->filter, len)) - goto out; - ret = 0; -out: return ret; + opt->optlen = len; + if (copy_to_iter(&raw_sk(sk)->filter, len, &opt->iter_out) != len) + return -EFAULT; + return 0; } static int do_raw_setsockopt(struct sock *sk, int optname, @@ -848,14 +843,13 @@ static int raw_setsockopt(struct sock *sk, int level, int optname, return do_raw_setsockopt(sk, optname, optval, optlen); } -static int do_raw_getsockopt(struct sock *sk, int optname, - char __user *optval, int __user *optlen) +static int do_raw_getsockopt(struct sock *sk, int optname, sockopt_t *opt) { if (optname == ICMP_FILTER) { if (inet_sk(sk)->inet_num != IPPROTO_ICMP) return -EOPNOTSUPP; else - return raw_geticmpfilter(sk, optval, optlen); + return raw_geticmpfilter(sk, opt); } return -ENOPROTOOPT; } @@ -863,9 +857,24 @@ static int do_raw_getsockopt(struct sock *sk, int optname, static int raw_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { + sockopt_t opt; + int err; + if (level != SOL_RAW) return ip_getsockopt(sk, level, optname, optval, optlen); - return do_raw_getsockopt(sk, optname, optval, optlen); + + err = sockopt_init_user(&opt, optval, optlen); + if (err) + return err; + + err = do_raw_getsockopt(sk, optname, &opt); + if (err) + return err; + + if (put_user(opt.optlen, optlen)) + return -EFAULT; + + return 0; } static int raw_ioctl(struct sock *sk, int cmd, int *karg) -- 2.53.0-Meta

