lkml.org 
[lkml]   [2022]   [Aug]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.19 065/158] net: Fix data-races around sysctl_[rw]mem_(max|default).
    Date
    From: Kuniyuki Iwashima <kuniyu@amazon.com>

    [ Upstream commit 1227c1771dd2ad44318aa3ab9e3a293b3f34ff2a ]

    While reading sysctl_[rw]mem_(max|default), they can be changed
    concurrently. Thus, we need to add READ_ONCE() to its readers.

    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
    Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/core/filter.c | 4 ++--
    net/core/sock.c | 8 ++++----
    net/ipv4/ip_output.c | 2 +-
    net/ipv4/tcp_output.c | 2 +-
    net/netfilter/ipvs/ip_vs_sync.c | 4 ++--
    5 files changed, 10 insertions(+), 10 deletions(-)

    diff --git a/net/core/filter.c b/net/core/filter.c
    index 74f05ed6aff29..60c854e7d98ba 100644
    --- a/net/core/filter.c
    +++ b/net/core/filter.c
    @@ -5036,14 +5036,14 @@ static int _bpf_setsockopt(struct sock *sk, int level, int optname,
    /* Only some socketops are supported */
    switch (optname) {
    case SO_RCVBUF:
    - val = min_t(u32, val, sysctl_rmem_max);
    + val = min_t(u32, val, READ_ONCE(sysctl_rmem_max));
    val = min_t(int, val, INT_MAX / 2);
    sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
    WRITE_ONCE(sk->sk_rcvbuf,
    max_t(int, val * 2, SOCK_MIN_RCVBUF));
    break;
    case SO_SNDBUF:
    - val = min_t(u32, val, sysctl_wmem_max);
    + val = min_t(u32, val, READ_ONCE(sysctl_wmem_max));
    val = min_t(int, val, INT_MAX / 2);
    sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
    WRITE_ONCE(sk->sk_sndbuf,
    diff --git a/net/core/sock.c b/net/core/sock.c
    index 2ff40dd0a7a65..62f69bc3a0e6e 100644
    --- a/net/core/sock.c
    +++ b/net/core/sock.c
    @@ -1100,7 +1100,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
    * play 'guess the biggest size' games. RCVBUF/SNDBUF
    * are treated in BSD as hints
    */
    - val = min_t(u32, val, sysctl_wmem_max);
    + val = min_t(u32, val, READ_ONCE(sysctl_wmem_max));
    set_sndbuf:
    /* Ensure val * 2 fits into an int, to prevent max_t()
    * from treating it as a negative value.
    @@ -1132,7 +1132,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
    * play 'guess the biggest size' games. RCVBUF/SNDBUF
    * are treated in BSD as hints
    */
    - __sock_set_rcvbuf(sk, min_t(u32, val, sysctl_rmem_max));
    + __sock_set_rcvbuf(sk, min_t(u32, val, READ_ONCE(sysctl_rmem_max)));
    break;

    case SO_RCVBUFFORCE:
    @@ -3307,8 +3307,8 @@ void sock_init_data(struct socket *sock, struct sock *sk)
    timer_setup(&sk->sk_timer, NULL, 0);

    sk->sk_allocation = GFP_KERNEL;
    - sk->sk_rcvbuf = sysctl_rmem_default;
    - sk->sk_sndbuf = sysctl_wmem_default;
    + sk->sk_rcvbuf = READ_ONCE(sysctl_rmem_default);
    + sk->sk_sndbuf = READ_ONCE(sysctl_wmem_default);
    sk->sk_state = TCP_CLOSE;
    sk_set_socket(sk, sock);

    diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
    index 00b4bf26fd932..da8b3cc67234d 100644
    --- a/net/ipv4/ip_output.c
    +++ b/net/ipv4/ip_output.c
    @@ -1712,7 +1712,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,

    sk->sk_protocol = ip_hdr(skb)->protocol;
    sk->sk_bound_dev_if = arg->bound_dev_if;
    - sk->sk_sndbuf = sysctl_wmem_default;
    + sk->sk_sndbuf = READ_ONCE(sysctl_wmem_default);
    ipc.sockc.mark = fl4.flowi4_mark;
    err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
    len, 0, &ipc, &rt, MSG_DONTWAIT);
    diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
    index aed0c5f828bef..84314de754f87 100644
    --- a/net/ipv4/tcp_output.c
    +++ b/net/ipv4/tcp_output.c
    @@ -239,7 +239,7 @@ void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss,
    if (wscale_ok) {
    /* Set window scaling on max possible window */
    space = max_t(u32, space, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2]));
    - space = max_t(u32, space, sysctl_rmem_max);
    + space = max_t(u32, space, READ_ONCE(sysctl_rmem_max));
    space = min_t(u32, space, *window_clamp);
    *rcv_wscale = clamp_t(int, ilog2(space) - 15,
    0, TCP_MAX_WSCALE);
    diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
    index 9d43277b8b4fe..a56fd0b5a430a 100644
    --- a/net/netfilter/ipvs/ip_vs_sync.c
    +++ b/net/netfilter/ipvs/ip_vs_sync.c
    @@ -1280,12 +1280,12 @@ static void set_sock_size(struct sock *sk, int mode, int val)
    lock_sock(sk);
    if (mode) {
    val = clamp_t(int, val, (SOCK_MIN_SNDBUF + 1) / 2,
    - sysctl_wmem_max);
    + READ_ONCE(sysctl_wmem_max));
    sk->sk_sndbuf = val * 2;
    sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
    } else {
    val = clamp_t(int, val, (SOCK_MIN_RCVBUF + 1) / 2,
    - sysctl_rmem_max);
    + READ_ONCE(sysctl_rmem_max));
    sk->sk_rcvbuf = val * 2;
    sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
    }
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-08-29 14:17    [W:4.194 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site