Add a helper that initializes a user-backed sockopt_t from the
(optval, optlen) __user pair passed to a getsockopt() callback.

It is used by transitional __user getsockopt wrappers while the
proto-layer getsockopt callbacks are converted to take a sockopt_t, and
is removed once the conversion is complete.

The goal is to help to convert leafs. Example:

 sock_common_getsockopt(... char __user *optval, int __user *optlen)
      → udp_getsockopt(sk, level, optname, optval__user, optlen__user)
               → udp_lib_getsockopt(sk, level, optname, &opt)   /* needs a 
sockopt_t */

Signed-off-by: Breno Leitao <[email protected]>
---
 include/linux/net.h | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/include/linux/net.h b/include/linux/net.h
index f268f395ce473..277188a40c72e 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -47,6 +47,29 @@ typedef struct sockopt {
        int optlen;
 } sockopt_t;
 
+/*
+ * Initialize a user-backed sockopt_t from the (optval, optlen) __user pair of
+ * a getsockopt() callback. Used by transitional __user getsockopt wrappers
+ * while the proto-layer callbacks are converted to take a sockopt_t; the
+ * caller writes opt->optlen back to the user optlen after the callback.
+ */
+static inline int sockopt_init_user(sockopt_t *opt, char __user *optval,
+                                   int __user *optlen)
+{
+       int len;
+
+       if (get_user(len, optlen))
+               return -EFAULT;
+       if (len < 0)
+               return -EINVAL;
+
+       iov_iter_ubuf(&opt->iter_out, ITER_DEST, optval, len);
+       iov_iter_ubuf(&opt->iter_in, ITER_SOURCE, optval, len);
+       opt->optlen = len;
+
+       return 0;
+}
+
 struct poll_table_struct;
 struct pipe_inode_info;
 struct inode;

-- 
2.53.0-Meta


Reply via email to