From: Konstantin Khorenko <khore...@virtuozzo.com>

In do_ip_setsockopt() IP_MSFILTER and MCAST_MSFILTER cases
allocates memory size which depends on userspace but not greater than
sysctl_optmem_max (net.core.optmem_max which is 20480 by default) =>
3rd order page allocations are possible here =>

substitute kmalloc() with kvmalloc() here.

  WARNING: CPU: 2 PID: 34605 at mm/page_alloc.c:3197 
__alloc_pages_nodemask+0x2e4/0x590
  order 3 >= 3, gfp 0x40d0
  Modules linked in: <skipped>
  CPU: 2 PID: 34605 Comm: trinity-main ve: d7d30d09-1585-4ef1-99b9-893b4fb06cec 
Not tainted 3.10.0-693.17.1.vz7.45.8 #1 45.8
  Hardware name: Virtuozzo KVM, BIOS 1.10.2-3.1.vz7.2 04/01/2014
  Call Trace:
  [<ffffffff816d6d81>] dump_stack+0x19/0x1b
  [<ffffffff8108a8d8>] __warn+0xd8/0x100
  [<ffffffff8108a95f>] warn_slowpath_fmt+0x5f/0x80
  [<ffffffff811a12c4>] __alloc_pages_nodemask+0x2e4/0x590
  [<ffffffff811ea978>] alloc_pages_current+0x98/0x110
  [<ffffffff811bd498>] kmalloc_order+0x18/0x40
  [<ffffffff811bd4e6>] kmalloc_order_trace+0x26/0xa0
  [<ffffffff811f9399>] __kmalloc+0x279/0x290
  [<ffffffff81604277>] do_ip_setsockopt.isra.15+0x507/0xeb0
  [<ffffffff81604c50>] ip_setsockopt+0x30/0xd0
  [<ffffffff8162b9fb>] udp_setsockopt+0x1b/0x40
  [<ffffffff8168bee6>] ipv6_setsockopt+0x46/0xd0
  [<ffffffff81690d7b>] udpv6_setsockopt+0x1b/0x40
  [<ffffffff8159d204>] sock_common_setsockopt+0x14/0x20
  [<ffffffff8159c390>] SyS_setsockopt+0x80/0xf0
  [<ffffffff816e9a7d>] system_call_fastpath+0x16/0x1b
  ---[ end trace 5b208f01e4177b5b ]---

https://jira.sw.ru/browse/PSBM-82646

Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com>

(cherry picked from vz7 commit ce5cdfafdb37 ("net/setsockopt: switch high order
allocations to kvmalloc() in do_ip_setsockopt()"))

See also a2c841d94 ("do_ip_setsockopt(): don't open-code memdup_user()")
memdup_user -> vmemdup_user

VZ 8 rebase part https://jira.sw.ru/browse/PSBM-127798

Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalit...@virtuozzo.com>

Rebased to vz9:
 - MCAST_MSFILTER case was split into several functions:
ip_set_mcast_msfilter, compat_ip_set_mcast_msfilter(),
set_mcast_msfilter(). Change them to use kvmalloc.

(cherry picked from vz8 commit 5feac0a8dd7abf9ae2f6b2bda4eea7263ae9eeac)
Signed-off-by: Andrey Zhadchenko <andrey.zhadche...@virtuozzo.com>
---
 net/ipv4/ip_sockglue.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index ec60367..db16e24 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -668,7 +668,7 @@ static int set_mcast_msfilter(struct sock *sk, int ifindex,
        struct sockaddr_in *psin;
        int err, i;
 
-       msf = kmalloc(msize, GFP_KERNEL);
+       msf = kvmalloc(msize, GFP_KERNEL);
        if (!msf)
                return -ENOBUFS;
 
@@ -687,11 +687,11 @@ static int set_mcast_msfilter(struct sock *sk, int 
ifindex,
                msf->imsf_slist[i] = psin->sin_addr.s_addr;
        }
        err = ip_mc_msfilter(sk, msf, ifindex);
-       kfree(msf);
+       kvfree(msf);
        return err;
 
 Eaddrnotavail:
-       kfree(msf);
+       kvfree(msf);
        return -EADDRNOTAVAIL;
 }
 
@@ -776,7 +776,7 @@ static int ip_set_mcast_msfilter(struct sock *sk, sockptr_t 
optval, int optlen)
        if (optlen > sysctl_optmem_max)
                return -ENOBUFS;
 
-       gsf = memdup_sockptr(optval, optlen);
+       gsf = vmemdup_sockptr(optval, optlen);
        if (IS_ERR(gsf))
                return PTR_ERR(gsf);
 
@@ -793,7 +793,7 @@ static int ip_set_mcast_msfilter(struct sock *sk, sockptr_t 
optval, int optlen)
        err = set_mcast_msfilter(sk, gsf->gf_interface, gsf->gf_numsrc,
                                 gsf->gf_fmode, &gsf->gf_group, gsf->gf_slist);
 out_free_gsf:
-       kfree(gsf);
+       kvfree(gsf);
        return err;
 }
 
@@ -811,7 +811,7 @@ static int compat_ip_set_mcast_msfilter(struct sock *sk, 
sockptr_t optval,
        if (optlen > sysctl_optmem_max - 4)
                return -ENOBUFS;
 
-       p = kmalloc(optlen + 4, GFP_KERNEL);
+       p = kvmalloc(optlen + 4, GFP_KERNEL);
        if (!p)
                return -ENOMEM;
        gf32 = p + 4; /* we want ->gf_group and ->gf_slist aligned */
@@ -837,7 +837,7 @@ static int compat_ip_set_mcast_msfilter(struct sock *sk, 
sockptr_t optval,
        err = set_mcast_msfilter(sk, gf32->gf_interface, n, gf32->gf_fmode,
                                 &gf32->gf_group, gf32->gf_slist);
 out_free_gsf:
-       kfree(p);
+       kvfree(p);
        return err;
 }
 
@@ -1235,7 +1235,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, 
int optname,
                        err = -ENOBUFS;
                        break;
                }
-               msf = memdup_sockptr(optval, optlen);
+               msf = vmemdup_sockptr(optval, optlen);
                if (IS_ERR(msf)) {
                        err = PTR_ERR(msf);
                        break;
@@ -1243,17 +1243,17 @@ static int do_ip_setsockopt(struct sock *sk, int level, 
int optname,
                /* numsrc >= (1G-4) overflow in 32 bits */
                if (msf->imsf_numsrc >= 0x3ffffffcU ||
                    msf->imsf_numsrc > net->ipv4.sysctl_igmp_max_msf) {
-                       kfree(msf);
+                       kvfree(msf);
                        err = -ENOBUFS;
                        break;
                }
                if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
-                       kfree(msf);
+                       kvfree(msf);
                        err = -EINVAL;
                        break;
                }
                err = ip_mc_msfilter(sk, msf, 0);
-               kfree(msf);
+               kvfree(msf);
                break;
        }
        case IP_BLOCK_SOURCE:
-- 
1.8.3.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to