Implement ->proc_write_buf() so procfs copies in what is written to
/proc/net/xt_recent/<table> before it pins the entry, and take the
address from that copy. The removal of a table runs under recent_mutex
and doesn't wait for a writer that faults on its buffer anymore. Writes
larger than PAGE_SIZE - 1 bytes fail with -EINVAL now.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 net/netfilter/xt_recent.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index b771cc463aab..306557f25daf 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -553,8 +553,7 @@ static int recent_seq_open(struct inode *inode, struct file 
*file)
 }
 
 static ssize_t
-recent_mt_proc_write(struct file *file, const char __user *input,
-                    size_t size, loff_t *loff)
+recent_mt_proc_write(struct file *file, char *input, size_t size, loff_t *loff)
 {
        struct recent_table *t = pde_data(file_inode(file));
        struct recent_entry *e;
@@ -568,8 +567,7 @@ recent_mt_proc_write(struct file *file, const char __user 
*input,
                return 0;
        if (size > sizeof(buf))
                size = sizeof(buf);
-       if (copy_from_user(buf, input, size) != 0)
-               return -EFAULT;
+       memcpy(buf, input, size);
 
        /* Strict protocol! */
        if (*loff != 0)
@@ -625,7 +623,7 @@ static const struct proc_ops recent_mt_proc_ops = {
        .proc_seq_ops   = &recent_seq_ops,
        .proc_state_size = sizeof(struct recent_iter_state),
        .proc_open      = recent_seq_open,
-       .proc_write     = recent_mt_proc_write,
+       .proc_write_buf = recent_mt_proc_write,
 };
 
 static int __net_init recent_proc_net_init(struct net *net)

-- 
2.53.0


Reply via email to