• Ido Schimmel's avatar
    drop_monitor: Require 'CAP_SYS_ADMIN' when joining "events" group · e0378187
    Ido Schimmel authored
    The "NET_DM" generic netlink family notifies drop locations over the
    "events" multicast group. This is problematic since by default generic
    netlink allows non-root users to listen to these notifications.
    
    Fix by adding a new field to the generic netlink multicast group
    structure that when set prevents non-root users or root without the
    'CAP_SYS_ADMIN' capability (in the user namespace owning the network
    namespace) from joining the group. Set this field for the "events"
    group. Use 'CAP_SYS_ADMIN' rather than 'CAP_NET_ADMIN' because of the
    nature of the information that is shared over this group.
    
    Note that the capability check in this case will always be performed
    against the initial user namespace since the family is not netns aware
    and only operates in the initial network namespace.
    
    A new field is added to the structure rather than using the "flags"
    field because the existing field uses uAPI flags and it is inappropriate
    to add a new uAPI flag for an internal kernel check. In net-next we can
    rework the "flags" field to use internal flags and fold the new field
    into it. But for now, in order to reduce the amount of changes, add a
    new field.
    
    Since the information can only be consumed by root, mark the control
    plane operations that start and stop the tracing as root-only using the
    'GENL_ADMIN_PERM' flag.
    
    Tested using [1].
    
    Before:
    
     # capsh -- -c ./dm_repo
     # capsh --drop=cap_sys_admin -- -c ./dm_repo
    
    After:
    
     # capsh -- -c ./dm_repo
     # capsh --drop=cap_sys_admin -- -c ./dm_repo
     Failed to join "events" multicast group
    
    [1]
     $ cat dm.c
     #include <stdio.h>
     #include <netlink/genl/ctrl.h>
     #include <netlink/genl/genl.h>
     #include <netlink/socket.h>
    
     int main(int argc, char **argv)
     {
     	struct nl_sock *sk;
     	int grp, err;
    
     	sk = nl_socket_alloc();
     	if (!sk) {
     		fprintf(stderr, "Failed to allocate socket\n");
     		return -1;
     	}
    
     	err = genl_connect(sk);
     	if (err) {
     		fprintf(stderr, "Failed to connect socket\n");
     		return err;
     	}
    
     	grp = genl_ctrl_resolve_grp(sk, "NET_DM", "events");
     	if (grp < 0) {
     		fprintf(stderr,
     			"Failed to resolve \"events\" multicast group\n");
     		return grp;
     	}
    
     	err = nl_socket_add_memberships(sk, grp, NFNLGRP_NONE);
     	if (err) {
     		fprintf(stderr, "Failed to join \"events\" multicast group\n");
     		return err;
     	}
    
     	return 0;
     }
     $ gcc -I/usr/include/libnl3 -lnl-3 -lnl-genl-3 -o dm_repo dm.c
    
    Fixes: 9a8afc8d ("Network Drop Monitor: Adding drop monitor implementation & Netlink protocol")
    Reported-by: default avatar"The UK's National Cyber Security Centre (NCSC)" <security@ncsc.gov.uk>
    Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
    Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
    Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
    Link: https://lore.kernel.org/r/20231206213102.1824398-3-idosch@nvidia.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    e0378187
genetlink.c 41.4 KB