Commit graph

39 commits

Author SHA1 Message Date
Thomas Haller
17ae6a4413
platform: drop unused nl_socket_set_nonblocking() function
It's not used. It's better to use SOCK_NONBLOCK flag for socket(), as we do.

Also, the implementation that blindly calls F_SETFL without merging the
existing flags from F_GETFL is just wrong. Drop it altogether.
2023-04-04 08:43:20 +02:00
Corentin Noël
5d28a0dd89
doc: replace all (allow-none) annotations by (optional) and/or (nullable)
The (allow-none) annotation is deprecated since a long time now, it is better to
use (nullable) and/or (optional) which clarifies what it means with the (out)
annotation.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1551
2023-03-27 11:49:43 +02:00
Thomas Haller
1d69b41db9
platform: log extack warning messages for netlink requests
The extack can also be returned on success. In that case,
they are warnings. Log them, it might be useful.
2023-02-28 12:08:06 +01:00
Thomas Haller
6f854ecaeb
platform/netlink: cleanup nla_strlcpy() to not wipe remaining buffer
strlcpy()/g_strlcpy() has a well understood behavior. nla_strlcpy()
did not behave like that. Instead, it also used to always wipe the
remainder of the string, similar to what strncpy() would do.

True, if we do

  nla_strlcpy(obj->link.name, tb[IFLA_IFNAME], IFNAMSIZ);

then we might want to clear the remainder and don't care about the
overhead of writing up to 14 bytes unnecessarily... However, actually
all callers of nla_strlcpy() either operate on a buffer that is already
pre-inialized with zero, or they really don't care about the
uninitialized memory after the string. So this was nowhere the desired
behavior.

Change nla_strlcpy() to not wipe the remainder of the buffer, so it behaves
mostly like strlcpy()/g_strlcpy() and as one would expect.

Add nla_strlcpy_wipe(), which on top of it also clears the remaining
buffer. In that aspect, it bears some similarities with strncpy(), but it
differs in other regards from strncpy (always NUL terminating and
returning the srclen). Yes, the name nla_strlcpy_wipe() is maybe
unfamiliar to the user, but it really is like nla_strlcpy() with the
addition to clear the buffer. That seems simple enough to understand
based on the name.

Note that all existing callers of nla_strlcpy() do not care about
clearing the memory, and the change in behavior is fine for them.
2023-02-28 12:08:06 +01:00
Thomas Haller
36f8de25c4
all: fix various "-Wcast-align=strict" warnings
The warning "-Wcast-align=strict" seems useful and will be enabled
next. Fix places that currently cause the warning by using the
new macro NM_CAST_ALIGN(). This macro also nm_assert()s that the alignment
is correct.
2022-12-09 09:15:56 +01:00
Beniamino Galvani
f12d96f0fa platform: change nlmsg_alloc*() functions
Add a len argument to nlmsg_alloc() and nlmsg_alloc_simple(). After
that, nlmsg_alloc_size() can be dropped. Also, rename
nlmsg_alloc_simple() to nlmsg_alloc_new().
2022-10-17 10:30:44 +02:00
Thomas Haller
494b3d82c1
platform/netlink: add nlmsg_parse_error() helper 2022-08-09 08:02:40 +02:00
Thomas Haller
c74c783c28
platform/netlink: make callback parameters to nl_recvmsg() const 2022-08-09 08:02:38 +02:00
Thomas Haller
45ca7dfaf3
platform/netlink: add NLA_S32 enum value for attribute type 2022-07-20 10:23:05 +02:00
Thomas Haller
19f14dbf37
platform/netlink: adjust integer types in netlink API
- use proper integer types. A netlink message cannot be as large as
  size_t, because the length is tracked in an uint32_t. Use the
  right types.

- fields like "nlmsg_type" or "nlmsg_flags" are uint16_t. Use the
  right types.

- note that nlmsg_size() still returns and accepts "int". Maybe
  the should be adjusted too, but we use macros from kernel headers,
  which also use int. Even if that is not the type of the length on
  the binary protocol. So some of these functions still use int, to
  be closer and compatible with <linux/netlink.h>.
2022-07-19 12:36:57 +02:00
Thomas Haller
9ef02ef7d0
platform/netlink: ensure padding is zero in _nest_end()
nla_reserve() also ensures that the padding is zero, and only the
padding. Thus, when we call nla_reserve(), we need to zero the padding
ourselves.
2022-07-19 12:33:49 +02:00
Lubomir Rintel
8e6f55ce82 platform: fix build with kernels < 5.7
Fixes: 919a61bc53 ('platform/netlink: extend nl_nlmsghdr_to_str() for genl messages')

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1280
2022-06-27 09:08:00 +02:00
Thomas Haller
f8e061d7d6
platform/netlink: expose genl_ctrl_policy policy in header 2022-06-24 11:03:40 +02:00
Thomas Haller
4f405c5a07
platform/netlink: drop nl_socket_set_ext_ack() API
We just always want to set this. No need for a setter that is only
called once.
2022-06-24 11:03:39 +02:00
Thomas Haller
9cd986ba2e
platform/netlink: simplify socket flags and use boolean fields
- replace "s_flags" field by explicit boolean fields.

- "s_msg_peek" now is simplified. Previously, we would default
  to peek, unless the user caller nl_socket_disable_msg_peek()
  or set nl_socket_set_msg_buf_size(). Simplify that. We now
  default to peek, unless NL_SOCKET_FLAGS_DISABLE_MSG_PEEK is set.

  We have no callers that call nl_socket_set_msg_buf_size(),
  so we can simplify that logic and just enable peeking by default.

- keep "s_auto_ack" field, although it is always TRUE and there
  is no API to toggle that. However, it is kept as a self-documenting
  thing, so we would know the relevant places where auto-ack matters.

- drop nl_socket_disable_msg_peek(). We have no caller of this function
  and we can set peeking in nl_socket_new(). We also don't need to
  change it after creation of the socket.
2022-06-24 11:03:38 +02:00
Thomas Haller
c09b37f3c7
platform/netlink: add flags argument to nl_socket_new()
The real purpose is that we set the socket options before bind().
For that, we need to be able to specify the flag during nl_socket_new().

Another reason is that these are common questions to ponder while
creating a netlink socket. There shouldn't be several setter functions,
just specify the flag right away. These parameters are not going to
change afterwards (at least, we don't need/use that and we don't have
API for that either).
2022-06-24 11:03:37 +02:00
Thomas Haller
919a61bc53
platform/netlink: extend nl_nlmsghdr_to_str() for genl messages
Print more details for generic netlink messages.

Also, pass the group that we obtained via NETLINK_PKTINFO.

Also, factor out simple to-string methods.
2022-06-24 11:03:36 +02:00
Thomas Haller
51b707357d
platform/netlink: add reading NETLINK_PKTINFO in nl_recv()
We will need this, for getting nl_pktinfo control messages
that contain the extended destination group number.

Also, drop NL_SOCK_PASSCRED. It was only used to not iterate over the
control messages, but doing that should be cheap.
2022-06-24 11:03:35 +02:00
Thomas Haller
1460adc918
platform/netlink: add const modifier for genl functions 2022-06-24 11:03:33 +02:00
Thomas Haller
59f577df56
platform/netlink: add const modifier to netlink header pointers
They are not supposed to be modified.
2022-06-23 20:36:53 +02:00
Thomas Haller
80afc691d5
platform/netlink: add "rxbuf/txbuf" arguments to nl_socket_new() 2022-06-23 20:36:52 +02:00
Thomas Haller
260d693ec4
platform/netlink: add "blocking" argument to nl_socket_new()
Whether we use a socket blockingly or non-blocking is usually determined
upfront and does not change. Make it a parameter of nl_socket_new().
Also, it saves an additional syscall.
2022-06-23 20:36:52 +02:00
Thomas Haller
f5d9428468
platform/netlink: add netlink_protocol argument to nl_nlmsghdr_to_str()
The meaning of the header depends on the netlink protocol. Add that parameter,
so we can also handle genl.
2022-06-17 19:40:37 +02:00
Thomas Haller
67d64fd4e5
platform/netlink: also set NETLINK_EXT_ACK for genl socket
There are only two callers of nl_socket_new(). One for NETLINK_GENERIC
and one for NETLINK_ROUTE.

We already were enabling ext-ack for the rtnetlink socket. Also enable
it for the genl socket.

Do that, but just moving this inside nl_socket_new(). I cannot imagine a
case where we don't want this.
2022-06-17 19:40:36 +02:00
Thomas Haller
f96fbc8ebe
platform/netlink: combine nl_socket_alloc() and nl_connect()
Create and use new nl_socket_new().

nl_socket_alloc() really does nothing but allocating the struct and
initializing the fd to -1. In all cases, we want to call nl_connect()
right after.

Combine the two. Then we also cannot  have a "struct nl_sock" without a
valid fd. This means several error checks can be dropped.

Note that former nl_connect() did several things at once. Maybe, for
more flexibility one would need to tweak what should be done there.
For now that is not necessary. In any case, if we need more flexibility,
then we would control what nl_connect() (now nl_socket_new()) does, and not
the split between nl_socket_alloc() and nl_connect().
2022-06-17 19:40:20 +02:00
Thomas Haller
d73594682f
platform: no need to initialize nla sockaddr parameter to nl_recv()
We always call nl_recv() in a loop. If it would be necessary to clear
the variable, then it would need to happen inside the loop. But it's
not necessary.
2022-02-03 13:11:17 +01:00
Thomas Haller
e8cfa22929
platform/netlink: accept pre-allocated receive buffer for nl_recv()
Add parameter to accept a pre-allocated buffer for nl_recv(). In
practice, rtnetlink messages are not larger than 32k, so we can always
pre-allocate it and avoid the need to heap allocate it.
2022-02-03 13:08:47 +01:00
Thomas Haller
c37a21ea29
Revert "platform: add bpf filter to ignore routes from routing daemons"
The socket BPF filter operates on the entire message (skb). One netlink
message (for RTM_NEWROUTE) usually contains a list of routes (struct
nlmsghdr), but the BPF filter was only looking at the first route to decide
whether to throw away the entire message. That is wrong.

This causes that we miss routes. It also means that the response to our
RTM_GETROUTE dump request could be filtered and we poll/wait (unsuccessfully)
for it:

  <trace> [1641829930.4111] platform-linux: netlink: read: wait for ACK for sequence number 26...

To get this right, the BPF filter would have to look at all routes in the
list to find out whether there are any we want to receive (and if
there are any, to pass the entire message, regardless that is might also
contain routes we want to ignore). As BPF does not support loops, that
is not trivial. Arguably, we still could do something where we look at a
bounded, unrolled number of routes, in the hope that there are not more
routes in one message that we support. The problem is that this BPF
filter is supposed to filter out massive amounts of routes, so most
messages will be filled to the brim with routes and we would have to
expect a high number of routes in the RTM_NEWROUTE that need checking.

We could still ignore routes in _new_from_nl_route(), to enter the
cache. That means, we would catch them later than with the BPF filter,
but still before a lot of the overhead of handling them. That probably
will be done next, but for now revert the commit.

This reverts commit e9ca5583e5.

https://bugzilla.redhat.com/show_bug.cgi?id=2037411
2022-01-20 10:30:30 +01:00
Beniamino Galvani
e9ca5583e5 platform: add bpf filter to ignore routes from routing daemons
Routing daemons can add a large amount of routes to the
system. Currently NM receives netlink notifications for all those
routes and exposes them on D-Bus. With many routes, the daemon becomes
increasingly slow and uses a lot of memory.

The rtm_protocol field of the route indicates the source of the
route. From /usr/include/linux/rtnetlink.h, the allowed values are:

  #define RTPROT_UNSPEC          0
  #define RTPROT_REDIRECT        1        /* Route installed by ICMP redirects;
                                             not used by current IPv4 */
  #define RTPROT_KERNEL          2        /* Route installed by kernel */
  #define RTPROT_BOOT            3        /* Route installed during boot */
  #define RTPROT_STATIC          4        /* Route installed by administrator */

  /* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
     they are just passed from user and back as is.
     It will be used by hypothetical multiple routing daemons.
     Note that protocol values should be standardized in order to
     avoid conflicts.
   */

  #define RTPROT_GATED           8        /* Apparently, GateD */
  #define RTPROT_RA              9        /* RDISC/ND router advertisements */
  #define RTPROT_MRT            10        /* Merit MRT */
  #define RTPROT_ZEBRA          11        /* Zebra */
  #define RTPROT_BIRD           12        /* BIRD */
  #define RTPROT_DNROUTED       13        /* DECnet routing daemon */
  #define RTPROT_XORP           14        /* XORP */
  #define RTPROT_NTK            15        /* Netsukuku */
  #define RTPROT_DHCP           16        /* DHCP client */
  #define RTPROT_MROUTED        17        /* Multicast daemon */
  #define RTPROT_KEEPALIVED     18        /* Keepalived daemon */
  #define RTPROT_BABEL          42        /* Babel daemon */
  #define RTPROT_OPENR          99        /* Open Routing (Open/R) Routes */
  #define RTPROT_BGP           186        /* BGP Routes */
  #define RTPROT_ISIS          187        /* ISIS Routes */
  #define RTPROT_OSPF          188        /* OSPF Routes */
  #define RTPROT_RIP           189        /* RIP Routes */
  #define RTPROT_EIGRP         192        /* EIGRP Routes */

Since NM uses only values <= RTPROT_STATIC, plus RTPROT_RA and
RTPROT_DHCP, add a BPF filter to the netlink socket to discard
notifications for other route types.

https://bugzilla.redhat.com/show_bug.cgi?id=1861527
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1038
2021-12-09 13:19:45 +01:00
Thomas Haller
615221a99c format: reformat source tree with clang-format 13.0
We use clang-format for automatic formatting of our source files.
Since clang-format is actively maintained software, the actual
formatting depends on the used version of clang-format. That is
unfortunate and painful, but really unavoidable unless clang-format
would be strictly bug-compatible.

So the version that we must use is from the current Fedora release, which
is also tested by our gitlab-ci. Previously, we were using Fedora 34 with
clang-tools-extra-12.0.1-1.fc34.x86_64.

As Fedora 35 comes along, we need to update our formatting as Fedora 35
comes with version "13.0.0~rc1-1.fc35".
An alternative would be to freeze on version 12, but that has different
problems (like, it's cumbersome to rebuild clang 12 on Fedora 35 and it
would be cumbersome for our developers which are on Fedora 35 to use a
clang that they cannot easily install).

The (differently painful) solution is to reformat from time to time, as we
switch to a new Fedora (and thus clang) version.
Usually we would expect that such a reformatting brings minor changes.
But this time, the changes are huge. That is mentioned in the release
notes [1] as

  Makes PointerAligment: Right working with AlignConsecutiveDeclarations. (Fixes https://llvm.org/PR27353)

[1] https://releases.llvm.org/13.0.0/tools/clang/docs/ReleaseNotes.html#clang-format
2021-11-29 09:31:09 +00:00
Thomas Haller
76bcd78710
platform/netlink: use appropriate integer types in nla_policy 2021-08-17 13:18:08 +02:00
Thomas Haller
f7635c9ffe
platform/netlink: use switch for type check in validate_nla() 2021-08-17 13:18:07 +02:00
Thomas Haller
68a5d1cfe5
platform/netlink: refactor handling length in validate_nla() 2021-08-17 13:18:07 +02:00
Thomas Haller
386b367bfa
platform/netlink: cleanup handling of nla_attr_minlen
- make nla_attr_minlen[] and array of uint8_t. That is large enough for
  all values we have.

- don't handle NLA_UNSPEC specially. nla_attr_minlen[NLA_UNSPEC] returns
  zero just fine.
2021-08-17 13:18:06 +02:00
Thomas Haller
d0ba87a1ad
all: rename nm_utils_strbuf_*() API to nm_strbuf_*()
The "utils" part does not seem useful in the name.

Note that we also have NMStrBuf, which is named nm_str_buf_*().
There is an unfortunate similarity between the two, but it's still
distinct enough (in particular, because one takes an NMStrBuf and
the other not).
2021-08-02 09:26:42 +02:00
Thomas Haller
4e109bacab
clang-format: use "IndentPPDirectives:None" instead of "BeforeHash"
Subjectively, I think this looks better.
2021-07-09 08:49:06 +02:00
Thomas Haller
5740ed67cb
platform/netlink: don't reallocate ancillary data for recvmsg() on truncation
Coverity thinks there is a problem here:

    Error: TAINTED_SCALAR (CWE-20): [#def233]
    NetworkManager-1.31.5/src/libnm-platform/nm-netlink.c:1437: tainted_argument: Calling function "recvmsg" taints argument "msg".
    NetworkManager-1.31.5/src/libnm-platform/nm-netlink.c:1458: tainted_data: Passing tainted expression "msg.msg_controllen" to "g_realloc", which uses it as an allocation size.
    NetworkManager-1.31.5/src/libnm-platform/nm-netlink.c:1458: remediation: Ensure that tainted values are properly sanitized, by checking that their values are within a permissible range.
    # 1456|
    # 1457|           msg.msg_controllen *= 2;
    # 1458|->         msg.msg_control = g_realloc(msg.msg_control, msg.msg_controllen);
    # 1459|           goto retry;
    # 1460|       }

but the problem is not the tainted data. The problem is how should
we handle MSG_CTRUNC? If we reach MSG_CTRUNC we already lost a message.
Retrying to receive the next message is not going to fix that and is
wrong.

Also, there really is no reason why any truncation should happen. The only
ancillary data that should be present is the sender information, and for
that our buffer is supposed to be large enough.

So, simply ignore truncation. It shouldn't happen, if it happened we
cannot recover from it (aside failing an assertion), and all we really
care are the retrieved credentials. If truncation happened, we might
not have retrieved the credentials, but then that is for the caller
to handle (by rejecting the message as untrusted).

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/872
2021-06-01 09:37:36 +02:00
Thomas Haller
9dc84b32b0
build: move "shared/nm-{glib-aux,log-null,log-core}" to "src/libnm-{glib-aux,log-null,log-core}" 2021-02-24 12:48:20 +01:00
Thomas Haller
2439374457
build: move "shared/nm-platform" to "src/libnm-platform" 2021-02-24 12:48:17 +01:00
Renamed from shared/nm-platform/nm-netlink.c (Browse further)