lkml.org 
[lkml]   [2019]   [Oct]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 26/93] ipv4: Return -ENETUNREACH if we cant create route but saddr is valid
    Date
    From: Stefano Brivio <sbrivio@redhat.com>

    [ Upstream commit 595e0651d0296bad2491a4a29a7a43eae6328b02 ]

    ...instead of -EINVAL. An issue was found with older kernel versions
    while unplugging a NFS client with pending RPCs, and the wrong error
    code here prevented it from recovering once link is back up with a
    configured address.

    Incidentally, this is not an issue anymore since commit 4f8943f80883
    ("SUNRPC: Replace direct task wakeups from softirq context"), included
    in 5.2-rc7, had the effect of decoupling the forwarding of this error
    by using SO_ERROR in xs_wake_error(), as pointed out by Benjamin
    Coddington.

    To the best of my knowledge, this isn't currently causing any further
    issue, but the error code doesn't look appropriate anyway, and we
    might hit this in other paths as well.

    In detail, as analysed by Gonzalo Siero, once the route is deleted
    because the interface is down, and can't be resolved and we return
    -EINVAL here, this ends up, courtesy of inet_sk_rebuild_header(),
    as the socket error seen by tcp_write_err(), called by
    tcp_retransmit_timer().

    In turn, tcp_write_err() indirectly calls xs_error_report(), which
    wakes up the RPC pending tasks with a status of -EINVAL. This is then
    seen by call_status() in the SUN RPC implementation, which aborts the
    RPC call calling rpc_exit(), instead of handling this as a
    potentially temporary condition, i.e. as a timeout.

    Return -EINVAL only if the input parameters passed to
    ip_route_output_key_hash_rcu() are actually invalid (this is the case
    if the specified source address is multicast, limited broadcast or
    all zeroes), but return -ENETUNREACH in all cases where, at the given
    moment, the given source address doesn't allow resolving the route.

    While at it, drop the initialisation of err to -ENETUNREACH, which
    was added to __ip_route_output_key() back then by commit
    0315e3827048 ("net: Fix behaviour of unreachable, blackhole and
    prohibit routes"), but actually had no effect, as it was, and is,
    overwritten by the fib_lookup() return code assignment, and anyway
    ignored in all other branches, including the if (fl4->saddr) one:
    I find this rather confusing, as it would look like -ENETUNREACH is
    the "default" error, while that statement has no effect.

    Also note that after commit fc75fc8339e7 ("ipv4: dont create routes
    on down devices"), we would get -ENETUNREACH if the device is down,
    but -EINVAL if the source address is specified and we can't resolve
    the route, and this appears to be rather inconsistent.

    Reported-by: Stefan Walter <walteste@inf.ethz.ch>
    Analysed-by: Benjamin Coddington <bcodding@redhat.com>
    Analysed-by: Gonzalo Siero <gsierohu@redhat.com>
    Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/ipv4/route.c | 9 ++++++---
    1 file changed, 6 insertions(+), 3 deletions(-)

    --- a/net/ipv4/route.c
    +++ b/net/ipv4/route.c
    @@ -2381,14 +2381,17 @@ struct rtable *ip_route_output_key_hash_
    int orig_oif = fl4->flowi4_oif;
    unsigned int flags = 0;
    struct rtable *rth;
    - int err = -ENETUNREACH;
    + int err;

    if (fl4->saddr) {
    - rth = ERR_PTR(-EINVAL);
    if (ipv4_is_multicast(fl4->saddr) ||
    ipv4_is_lbcast(fl4->saddr) ||
    - ipv4_is_zeronet(fl4->saddr))
    + ipv4_is_zeronet(fl4->saddr)) {
    + rth = ERR_PTR(-EINVAL);
    goto out;
    + }
    +
    + rth = ERR_PTR(-ENETUNREACH);

    /* I removed check for oif == dev_out->oif here.
    It was wrong for two reasons:

    \
     
     \ /
      Last update: 2019-10-27 22:33    [W:4.191 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site