mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 15:39:42 -04:00
Merge tag 'net-5.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Including fixes from bpf.
Current release - regressions:
- vhost_net: fix OoB on sendmsg() failure
- mlx5: bridge, fix uninitialized variable usage
- bnxt_en: fix error recovery regression
Current release - new code bugs:
- bpf, mm: fix lockdep warning triggered by stack_map_get_build_id_offset()
Previous releases - regressions:
- r6040: restore MDIO clock frequency after MAC reset
- tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
- dsa: flush switchdev workqueue before tearing down CPU/DSA ports
Previous releases - always broken:
- ptp: dp83640: don't define PAGE0, avoid compiler warning
- igc: fix tunnel segmentation offloads
- phylink: update SFP selected interface on advertising changes
- stmmac: fix system hang caused by eee_ctrl_timer during suspend/resume
- mlx5e: fix mutual exclusion between CQE compression and HW TS
Misc:
- bpf, cgroups: fix cgroup v2 fallback on v1/v2 mixed mode
- sfc: fallback for lack of xdp tx queues
- hns3: add option to turn off page pool feature"
* tag 'net-5.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (67 commits)
mlxbf_gige: clear valid_polarity upon open
igc: fix tunnel offloading
net/{mlx5|nfp|bnxt}: Remove unnecessary RTNL lock assert
net: wan: wanxl: define CROSS_COMPILE_M68K
selftests: nci: replace unsigned int with int
net: dsa: flush switchdev workqueue before tearing down CPU/DSA ports
Revert "net: phy: Uniform PHY driver access"
net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup
ptp: dp83640: don't define PAGE0
bnx2x: Fix enabling network interfaces without VFs
Revert "Revert "ipv4: fix memory leaks in ip_cmsg_send() callers""
tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
net-caif: avoid user-triggerable WARN_ON(1)
bpf, selftests: Add test case for mixed cgroup v1/v2
bpf, selftests: Add cgroup v1 net_cls classid helpers
bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode
bpf: Add oversize check before call kvcalloc()
net: hns3: fix the timing issue of VF clearing interrupt sources
net: hns3: fix the exception when query imp info
net: hns3: disable mac in flr process
...
This commit is contained in:
@@ -12,27 +12,36 @@
|
||||
#include <unistd.h>
|
||||
#include <ftw.h>
|
||||
|
||||
|
||||
#include "cgroup_helpers.h"
|
||||
|
||||
/*
|
||||
* To avoid relying on the system setup, when setup_cgroup_env is called
|
||||
* we create a new mount namespace, and cgroup namespace. The cgroup2
|
||||
* root is mounted at CGROUP_MOUNT_PATH
|
||||
* we create a new mount namespace, and cgroup namespace. The cgroupv2
|
||||
* root is mounted at CGROUP_MOUNT_PATH. Unfortunately, most people don't
|
||||
* have cgroupv2 enabled at this point in time. It's easier to create our
|
||||
* own mount namespace and manage it ourselves. We assume /mnt exists.
|
||||
*
|
||||
* Unfortunately, most people don't have cgroupv2 enabled at this point in time.
|
||||
* It's easier to create our own mount namespace and manage it ourselves.
|
||||
*
|
||||
* We assume /mnt exists.
|
||||
* Related cgroupv1 helpers are named *classid*(), since we only use the
|
||||
* net_cls controller for tagging net_cls.classid. We assume the default
|
||||
* mount under /sys/fs/cgroup/net_cls, which should be the case for the
|
||||
* vast majority of users.
|
||||
*/
|
||||
|
||||
#define WALK_FD_LIMIT 16
|
||||
|
||||
#define CGROUP_MOUNT_PATH "/mnt"
|
||||
#define CGROUP_MOUNT_DFLT "/sys/fs/cgroup"
|
||||
#define NETCLS_MOUNT_PATH CGROUP_MOUNT_DFLT "/net_cls"
|
||||
#define CGROUP_WORK_DIR "/cgroup-test-work-dir"
|
||||
|
||||
#define format_cgroup_path(buf, path) \
|
||||
snprintf(buf, sizeof(buf), "%s%s%s", CGROUP_MOUNT_PATH, \
|
||||
CGROUP_WORK_DIR, path)
|
||||
|
||||
#define format_classid_path(buf) \
|
||||
snprintf(buf, sizeof(buf), "%s%s", NETCLS_MOUNT_PATH, \
|
||||
CGROUP_WORK_DIR)
|
||||
|
||||
/**
|
||||
* enable_all_controllers() - Enable all available cgroup v2 controllers
|
||||
*
|
||||
@@ -139,8 +148,7 @@ static int nftwfunc(const char *filename, const struct stat *statptr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int join_cgroup_from_top(char *cgroup_path)
|
||||
static int join_cgroup_from_top(const char *cgroup_path)
|
||||
{
|
||||
char cgroup_procs_path[PATH_MAX + 1];
|
||||
pid_t pid = getpid();
|
||||
@@ -313,3 +321,114 @@ int cgroup_setup_and_join(const char *path) {
|
||||
}
|
||||
return cg_fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_classid_environment() - Setup the cgroupv1 net_cls environment
|
||||
*
|
||||
* After calling this function, cleanup_classid_environment should be called
|
||||
* once testing is complete.
|
||||
*
|
||||
* This function will print an error to stderr and return 1 if it is unable
|
||||
* to setup the cgroup environment. If setup is successful, 0 is returned.
|
||||
*/
|
||||
int setup_classid_environment(void)
|
||||
{
|
||||
char cgroup_workdir[PATH_MAX + 1];
|
||||
|
||||
format_classid_path(cgroup_workdir);
|
||||
|
||||
if (mount("tmpfs", CGROUP_MOUNT_DFLT, "tmpfs", 0, NULL) &&
|
||||
errno != EBUSY) {
|
||||
log_err("mount cgroup base");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mkdir(NETCLS_MOUNT_PATH, 0777) && errno != EEXIST) {
|
||||
log_err("mkdir cgroup net_cls");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mount("net_cls", NETCLS_MOUNT_PATH, "cgroup", 0, "net_cls") &&
|
||||
errno != EBUSY) {
|
||||
log_err("mount cgroup net_cls");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cleanup_classid_environment();
|
||||
|
||||
if (mkdir(cgroup_workdir, 0777) && errno != EEXIST) {
|
||||
log_err("mkdir cgroup work dir");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_classid() - Set a cgroupv1 net_cls classid
|
||||
* @id: the numeric classid
|
||||
*
|
||||
* Writes the passed classid into the cgroup work dir's net_cls.classid
|
||||
* file in order to later on trigger socket tagging.
|
||||
*
|
||||
* On success, it returns 0, otherwise on failure it returns 1. If there
|
||||
* is a failure, it prints the error to stderr.
|
||||
*/
|
||||
int set_classid(unsigned int id)
|
||||
{
|
||||
char cgroup_workdir[PATH_MAX - 42];
|
||||
char cgroup_classid_path[PATH_MAX + 1];
|
||||
int fd, rc = 0;
|
||||
|
||||
format_classid_path(cgroup_workdir);
|
||||
snprintf(cgroup_classid_path, sizeof(cgroup_classid_path),
|
||||
"%s/net_cls.classid", cgroup_workdir);
|
||||
|
||||
fd = open(cgroup_classid_path, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
log_err("Opening cgroup classid: %s", cgroup_classid_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dprintf(fd, "%u\n", id) < 0) {
|
||||
log_err("Setting cgroup classid");
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* join_classid() - Join a cgroupv1 net_cls classid
|
||||
*
|
||||
* This function expects the cgroup work dir to be already created, as we
|
||||
* join it here. This causes the process sockets to be tagged with the given
|
||||
* net_cls classid.
|
||||
*
|
||||
* On success, it returns 0, otherwise on failure it returns 1.
|
||||
*/
|
||||
int join_classid(void)
|
||||
{
|
||||
char cgroup_workdir[PATH_MAX + 1];
|
||||
|
||||
format_classid_path(cgroup_workdir);
|
||||
return join_cgroup_from_top(cgroup_workdir);
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup_classid_environment() - Cleanup the cgroupv1 net_cls environment
|
||||
*
|
||||
* At call time, it moves the calling process to the root cgroup, and then
|
||||
* runs the deletion process.
|
||||
*
|
||||
* On failure, it will print an error to stderr, and try to continue.
|
||||
*/
|
||||
void cleanup_classid_environment(void)
|
||||
{
|
||||
char cgroup_workdir[PATH_MAX + 1];
|
||||
|
||||
format_classid_path(cgroup_workdir);
|
||||
join_cgroup_from_top(NETCLS_MOUNT_PATH);
|
||||
nftw(cgroup_workdir, nftwfunc, WALK_FD_LIMIT, FTW_DEPTH | FTW_MOUNT);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __CGROUP_HELPERS_H
|
||||
#define __CGROUP_HELPERS_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -8,12 +9,21 @@
|
||||
#define log_err(MSG, ...) fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \
|
||||
__FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
||||
|
||||
|
||||
/* cgroupv2 related */
|
||||
int cgroup_setup_and_join(const char *path);
|
||||
int create_and_get_cgroup(const char *path);
|
||||
int join_cgroup(const char *path);
|
||||
int setup_cgroup_environment(void);
|
||||
void cleanup_cgroup_environment(void);
|
||||
unsigned long long get_cgroup_id(const char *path);
|
||||
|
||||
#endif
|
||||
int join_cgroup(const char *path);
|
||||
|
||||
int setup_cgroup_environment(void);
|
||||
void cleanup_cgroup_environment(void);
|
||||
|
||||
/* cgroupv1 related */
|
||||
int set_classid(unsigned int id);
|
||||
int join_classid(void);
|
||||
|
||||
int setup_classid_environment(void);
|
||||
void cleanup_classid_environment(void);
|
||||
|
||||
#endif /* __CGROUP_HELPERS_H */
|
||||
|
||||
@@ -208,11 +208,26 @@ int fastopen_connect(int server_fd, const char *data, unsigned int data_len,
|
||||
|
||||
static int connect_fd_to_addr(int fd,
|
||||
const struct sockaddr_storage *addr,
|
||||
socklen_t addrlen)
|
||||
socklen_t addrlen, const bool must_fail)
|
||||
{
|
||||
if (connect(fd, (const struct sockaddr *)addr, addrlen)) {
|
||||
log_err("Failed to connect to server");
|
||||
return -1;
|
||||
int ret;
|
||||
|
||||
errno = 0;
|
||||
ret = connect(fd, (const struct sockaddr *)addr, addrlen);
|
||||
if (must_fail) {
|
||||
if (!ret) {
|
||||
log_err("Unexpected success to connect to server");
|
||||
return -1;
|
||||
}
|
||||
if (errno != EPERM) {
|
||||
log_err("Unexpected error from connect to server");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (ret) {
|
||||
log_err("Failed to connect to server");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -257,7 +272,7 @@ int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts)
|
||||
strlen(opts->cc) + 1))
|
||||
goto error_close;
|
||||
|
||||
if (connect_fd_to_addr(fd, &addr, addrlen))
|
||||
if (connect_fd_to_addr(fd, &addr, addrlen, opts->must_fail))
|
||||
goto error_close;
|
||||
|
||||
return fd;
|
||||
@@ -289,7 +304,7 @@ int connect_fd_to_fd(int client_fd, int server_fd, int timeout_ms)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect_fd_to_addr(client_fd, &addr, len))
|
||||
if (connect_fd_to_addr(client_fd, &addr, len, false))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -20,6 +20,7 @@ typedef __u16 __sum16;
|
||||
struct network_helper_opts {
|
||||
const char *cc;
|
||||
int timeout_ms;
|
||||
bool must_fail;
|
||||
};
|
||||
|
||||
/* ipv4 test vector */
|
||||
|
||||
79
tools/testing/selftests/bpf/prog_tests/cgroup_v1v2.c
Normal file
79
tools/testing/selftests/bpf/prog_tests/cgroup_v1v2.c
Normal file
@@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <test_progs.h>
|
||||
|
||||
#include "connect4_dropper.skel.h"
|
||||
|
||||
#include "cgroup_helpers.h"
|
||||
#include "network_helpers.h"
|
||||
|
||||
static int run_test(int cgroup_fd, int server_fd, bool classid)
|
||||
{
|
||||
struct network_helper_opts opts = {
|
||||
.must_fail = true,
|
||||
};
|
||||
struct connect4_dropper *skel;
|
||||
int fd, err = 0;
|
||||
|
||||
skel = connect4_dropper__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
return -1;
|
||||
|
||||
skel->links.connect_v4_dropper =
|
||||
bpf_program__attach_cgroup(skel->progs.connect_v4_dropper,
|
||||
cgroup_fd);
|
||||
if (!ASSERT_OK_PTR(skel->links.connect_v4_dropper, "prog_attach")) {
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (classid && !ASSERT_OK(join_classid(), "join_classid")) {
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = connect_to_fd_opts(server_fd, &opts);
|
||||
if (fd < 0)
|
||||
err = -1;
|
||||
else
|
||||
close(fd);
|
||||
out:
|
||||
connect4_dropper__destroy(skel);
|
||||
return err;
|
||||
}
|
||||
|
||||
void test_cgroup_v1v2(void)
|
||||
{
|
||||
struct network_helper_opts opts = {};
|
||||
int server_fd, client_fd, cgroup_fd;
|
||||
static const int port = 60123;
|
||||
|
||||
/* Step 1: Check base connectivity works without any BPF. */
|
||||
server_fd = start_server(AF_INET, SOCK_STREAM, NULL, port, 0);
|
||||
if (!ASSERT_GE(server_fd, 0, "server_fd"))
|
||||
return;
|
||||
client_fd = connect_to_fd_opts(server_fd, &opts);
|
||||
if (!ASSERT_GE(client_fd, 0, "client_fd")) {
|
||||
close(server_fd);
|
||||
return;
|
||||
}
|
||||
close(client_fd);
|
||||
close(server_fd);
|
||||
|
||||
/* Step 2: Check BPF policy prog attached to cgroups drops connectivity. */
|
||||
cgroup_fd = test__join_cgroup("/connect_dropper");
|
||||
if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd"))
|
||||
return;
|
||||
server_fd = start_server(AF_INET, SOCK_STREAM, NULL, port, 0);
|
||||
if (!ASSERT_GE(server_fd, 0, "server_fd")) {
|
||||
close(cgroup_fd);
|
||||
return;
|
||||
}
|
||||
ASSERT_OK(run_test(cgroup_fd, server_fd, false), "cgroup-v2-only");
|
||||
setup_classid_environment();
|
||||
set_classid(42);
|
||||
ASSERT_OK(run_test(cgroup_fd, server_fd, true), "cgroup-v1v2");
|
||||
cleanup_classid_environment();
|
||||
close(server_fd);
|
||||
close(cgroup_fd);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#define _GNU_SOURCE
|
||||
#include <test_progs.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include "test_task_pt_regs.skel.h"
|
||||
|
||||
void test_task_pt_regs(void)
|
||||
|
||||
26
tools/testing/selftests/bpf/progs/connect4_dropper.c
Normal file
26
tools/testing/selftests/bpf/progs/connect4_dropper.c
Normal file
@@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/bpf.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
|
||||
#define VERDICT_REJECT 0
|
||||
#define VERDICT_PROCEED 1
|
||||
|
||||
SEC("cgroup/connect4")
|
||||
int connect_v4_dropper(struct bpf_sock_addr *ctx)
|
||||
{
|
||||
if (ctx->type != SOCK_STREAM)
|
||||
return VERDICT_PROCEED;
|
||||
if (ctx->user_port == bpf_htons(60123))
|
||||
return VERDICT_REJECT;
|
||||
return VERDICT_PROCEED;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
@@ -1,12 +1,17 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/bpf.h>
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
struct pt_regs current_regs = {};
|
||||
struct pt_regs ctx_regs = {};
|
||||
#define PT_REGS_SIZE sizeof(struct pt_regs)
|
||||
|
||||
/*
|
||||
* The kernel struct pt_regs isn't exported in its entirety to userspace.
|
||||
* Pass it as an array to task_pt_regs.c
|
||||
*/
|
||||
char current_regs[PT_REGS_SIZE] = {};
|
||||
char ctx_regs[PT_REGS_SIZE] = {};
|
||||
int uprobe_res = 0;
|
||||
|
||||
SEC("uprobe/trigger_func")
|
||||
@@ -17,8 +22,10 @@ int handle_uprobe(struct pt_regs *ctx)
|
||||
|
||||
current = bpf_get_current_task_btf();
|
||||
regs = (struct pt_regs *) bpf_task_pt_regs(current);
|
||||
__builtin_memcpy(¤t_regs, regs, sizeof(*regs));
|
||||
__builtin_memcpy(&ctx_regs, ctx, sizeof(*ctx));
|
||||
if (bpf_probe_read_kernel(current_regs, PT_REGS_SIZE, regs))
|
||||
return 0;
|
||||
if (bpf_probe_read_kernel(ctx_regs, PT_REGS_SIZE, ctx))
|
||||
return 0;
|
||||
|
||||
/* Prove that uprobe was run */
|
||||
uprobe_res = 1;
|
||||
|
||||
@@ -746,7 +746,7 @@ int read_write_nci_cmd(int nfc_sock, int virtual_fd, const __u8 *cmd, __u32 cmd_
|
||||
const __u8 *rsp, __u32 rsp_len)
|
||||
{
|
||||
char buf[256];
|
||||
unsigned int len;
|
||||
int len;
|
||||
|
||||
send(nfc_sock, &cmd[3], cmd_len - 3, 0);
|
||||
len = read(virtual_fd, buf, cmd_len);
|
||||
|
||||
@@ -45,7 +45,7 @@ altnames_test()
|
||||
check_err $? "Got unexpected long alternative name from link show JSON"
|
||||
|
||||
ip link property del $DUMMY_DEV altname $SHORT_NAME
|
||||
check_err $? "Failed to add short alternative name"
|
||||
check_err $? "Failed to delete short alternative name"
|
||||
|
||||
ip -j -p link show $SHORT_NAME &>/dev/null
|
||||
check_fail $? "Unexpected success while trying to do link show with deleted short alternative name"
|
||||
|
||||
Reference in New Issue
Block a user