| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/04 11:39 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"TUN"
],
"FocusSymbols": [
"tun_set_iff"
],
"Reasoning": "The patch introduces a new IFF_BACKPRESSURE flag for TUN/TAP devices, modifying the behavior of tun_net_xmit and __tun_wake_queue to stop the TX queue instead of dropping packets when the ring buffer is full. This is a functional change that can be reached via the TUNSETIFF ioctl.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/04 11:39 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 5c5f10f681e28569a47ab8a1d3529e4176a4ae98\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sat Jul 4 11:39:43 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/networking/tuntap.rst b/Documentation/networking/tuntap.rst\nindex 4d7087f727be5e..599264825dd216 100644\n--- a/Documentation/networking/tuntap.rst\n+++ b/Documentation/networking/tuntap.rst\n@@ -206,6 +206,23 @@ enable is true we enable it, otherwise we disable it::\n return ioctl(fd, TUNSETQUEUE, (void *)\u0026ifr);\n }\n \n+3.4 qdisc backpressure\n+----------------------\n+\n+Starting with Linux 7.2, IFF_BACKPRESSURE can be set to enable qdisc\n+backpressure. Without it, TX drops occur when the internal ring buffer is\n+full. With it, the kernel stops the TX queue instead, letting the qdisc\n+hold packets. Drops only occur as a rare race. This can benefit protocols\n+like TCP that react to drops. Backpressure requires a qdisc to be\n+attached and has no effect with noqueue.\n+\n+The TUN/TAP ring buffer size can be reduced alongside this flag to\n+further shift buffering into the qdisc and reduce bufferbloat, but comes\n+at possible performance cost.\n+\n+When running multiple network streams in parallel, the flag may reduce\n+performance due to the extra overhead of the backpressure mechanism.\n+\n Universal TUN/TAP device driver Frequently Asked Question\n =========================================================\n \ndiff --git a/drivers/net/tun.c b/drivers/net/tun.c\nindex ffbe6f13fb1fa2..3bf8a73a08162b 100644\n--- a/drivers/net/tun.c\n+++ b/drivers/net/tun.c\n@@ -98,7 +98,8 @@ static void tun_default_link_ksettings(struct net_device *dev,\n #define TUN_FASYNC\tIFF_ATTACH_QUEUE\n \n #define TUN_FEATURES (IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR | \\\n-\t\t IFF_MULTI_QUEUE | IFF_NAPI | IFF_NAPI_FRAGS)\n+\t\t IFF_MULTI_QUEUE | IFF_NAPI | IFF_NAPI_FRAGS | \\\n+\t\t IFF_BACKPRESSURE)\n \n #define GOODCOPY_LEN 128\n \n@@ -1077,7 +1078,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)\n \n \tspin_lock(\u0026tfile-\u003etx_ring.producer_lock);\n \tret = __ptr_ring_produce(\u0026tfile-\u003etx_ring, skb);\n-\tif (!qdisc_txq_has_no_queue(queue) \u0026\u0026\n+\tif ((tun-\u003eflags \u0026 IFF_BACKPRESSURE) \u0026\u0026\n+\t !qdisc_txq_has_no_queue(queue) \u0026\u0026\n \t __ptr_ring_check_produce(\u0026tfile-\u003etx_ring) == -ENOSPC) {\n \t\tnetif_tx_stop_queue(queue);\n \t\t/* Paired with smp_mb() in __tun_wake_queue() */\n@@ -2151,8 +2153,12 @@ static ssize_t tun_put_user(struct tun_struct *tun,\n static void __tun_wake_queue(struct tun_struct *tun,\n \t\t\t struct tun_file *tfile, int consumed)\n {\n-\tstruct netdev_queue *txq = netdev_get_tx_queue(tun-\u003edev,\n-\t\t\t\t\t\ttfile-\u003equeue_index);\n+\tstruct netdev_queue *txq;\n+\n+\tif (!(tun-\u003eflags \u0026 IFF_BACKPRESSURE))\n+\t\treturn;\n+\n+\ttxq = netdev_get_tx_queue(tun-\u003edev, tfile-\u003equeue_index);\n \n \t/* Paired with smp_mb__after_atomic() in tun_net_xmit() */\n \tsmp_mb();\n@@ -2893,8 +2899,19 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)\n \t/* Make sure persistent devices do not get stuck in\n \t * xoff state.\n \t */\n-\tif (netif_running(tun-\u003edev))\n-\t\tnetif_tx_wake_all_queues(tun-\u003edev);\n+\tif (netif_running(tun-\u003edev)) {\n+\t\tfor (int i = 0; i \u003c tun-\u003enumqueues; i++) {\n+\t\t\tstruct tun_file *i_tfile;\n+\n+\t\t\ti_tfile = rtnl_dereference(tun-\u003etfiles[i]);\n+\t\t\tspin_lock_bh(\u0026i_tfile-\u003etx_ring.consumer_lock);\n+\t\t\tspin_lock(\u0026i_tfile-\u003etx_ring.producer_lock);\n+\t\t\tnetif_wake_subqueue(tun-\u003edev, i_tfile-\u003equeue_index);\n+\t\t\ti_tfile-\u003econs_cnt = 0;\n+\t\t\tspin_unlock(\u0026i_tfile-\u003etx_ring.producer_lock);\n+\t\t\tspin_unlock_bh(\u0026i_tfile-\u003etx_ring.consumer_lock);\n+\t\t}\n+\t}\n \n \tstrscpy(ifr-\u003eifr_name, tun-\u003edev-\u003ename);\n \treturn 0;\ndiff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h\nindex 79d53c7a1ebdc5..73a77141315c7f 100644\n--- a/include/uapi/linux/if_tun.h\n+++ b/include/uapi/linux/if_tun.h\n@@ -69,6 +69,7 @@\n #define IFF_NAPI_FRAGS\t0x0020\n /* Used in TUNSETIFF to bring up tun/tap without carrier */\n #define IFF_NO_CARRIER\t0x0040\n+#define IFF_BACKPRESSURE\t0x0080\n #define IFF_NO_PI\t0x1000\n /* This flag has no real effect */\n #define IFF_ONE_QUEUE\t0x2000\ndiff --git a/tools/include/uapi/linux/if_tun.h b/tools/include/uapi/linux/if_tun.h\nindex 2ec07de1d73be4..97b670f5bc0a35 100644\n--- a/tools/include/uapi/linux/if_tun.h\n+++ b/tools/include/uapi/linux/if_tun.h\n@@ -67,6 +67,7 @@\n #define IFF_TAP\t\t0x0002\n #define IFF_NAPI\t0x0010\n #define IFF_NAPI_FRAGS\t0x0020\n+#define IFF_BACKPRESSURE\t0x0080\n #define IFF_NO_PI\t0x1000\n /* This flag has no real effect */\n #define IFF_ONE_QUEUE\t0x2000\n"
} |
| 2/1 | 2026/07/04 11:39 | agent | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"TUN"
],
"FocusSymbols": [
"tun_set_iff"
],
"Reasoning": "The patch introduces a new IFF_BACKPRESSURE flag for TUN/TAP devices, modifying the behavior of tun_net_xmit and __tun_wake_queue to stop the TX queue instead of dropping packets when the ring buffer is full. This is a functional change that can be reached via the TUNSETIFF ioctl.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 5c5f10f681e28569a47ab8a1d3529e4176a4ae98
Author: syz-cluster <triage@syzkaller.com>
Date: Sat Jul 4 11:39:43 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/networking/tuntap.rst b/Documentation/networking/tuntap.rst
index 4d7087f727be5e..599264825dd216 100644
--- a/Documentation/networking/tuntap.rst
+++ b/Documentation/networking/tuntap.rst
@@ -206,6 +206,23 @@ enable is true we enable it, otherwise we disable it::
return ioctl(fd, TUNSETQUEUE, (void *)&ifr);
}
+3.4 qdisc backpressure
+----------------------
+
+Starting with Linux 7.2, IFF_BACKPRESSURE can be set to enable qdisc
+backpressure. Without it, TX drops occur when the internal ring buffer is
+full. With it, the kernel stops the TX queue instead, letting the qdisc
+hold packets. Drops only occur as a rare race. This can benefit protocols
+like TCP that react to drops. Backpressure requires a qdisc to be
+attached and has no effect with noqueue.
+
+The TUN/TAP ring buffer size can be reduced alongside this flag to
+further shift buffering into the qdisc and reduce bufferbloat, but comes
+at possible performance cost.
+
+When running multiple network streams in parallel, the flag may reduce
+performance due to the extra overhead of the backpressure mechanism.
+
Universal TUN/TAP device driver Frequently Asked Question
=========================================================
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index ffbe6f13fb1fa2..3bf8a73a08162b 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -98,7 +98,8 @@ static void tun_default_link_ksettings(struct net_device *dev,
#define TUN_FASYNC IFF_ATTACH_QUEUE
#define TUN_FEATURES (IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR | \
- IFF_MULTI_QUEUE | IFF_NAPI | IFF_NAPI_FRAGS)
+ IFF_MULTI_QUEUE | IFF_NAPI | IFF_NAPI_FRAGS | \
+ IFF_BACKPRESSURE)
#define GOODCOPY_LEN 128
@@ -1077,7 +1078,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock(&tfile->tx_ring.producer_lock);
ret = __ptr_ring_produce(&tfile->tx_ring, skb);
- if (!qdisc_txq_has_no_queue(queue) &&
+ if ((tun->flags & IFF_BACKPRESSURE) &&
+ !qdisc_txq_has_no_queue(queue) &&
__ptr_ring_check_produce(&tfile->tx_ring) == -ENOSPC) {
netif_tx_stop_queue(queue);
/* Paired with smp_mb() in __tun_wake_queue() */
@@ -2151,8 +2153,12 @@ static ssize_t tun_put_user(struct tun_struct *tun,
static void __tun_wake_queue(struct tun_struct *tun,
struct tun_file *tfile, int consumed)
{
- struct netdev_queue *txq = netdev_get_tx_queue(tun->dev,
- tfile->queue_index);
+ struct netdev_queue *txq;
+
+ if (!(tun->flags & IFF_BACKPRESSURE))
+ return;
+
+ txq = netdev_get_tx_queue(tun->dev, tfile->queue_index);
/* Paired with smp_mb__after_atomic() in tun_net_xmit() */
smp_mb();
@@ -2893,8 +2899,19 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
/* Make sure persistent devices do not get stuck in
* xoff state.
*/
- if (netif_running(tun->dev))
- netif_tx_wake_all_queues(tun->dev);
+ if (netif_running(tun->dev)) {
+ for (int i = 0; i < tun->numqueues; i++) {
+ struct tun_file *i_tfile;
+
+ i_tfile = rtnl_dereference(tun->tfiles[i]);
+ spin_lock_bh(&i_tfile->tx_ring.consumer_lock);
+ spin_lock(&i_tfile->tx_ring.producer_lock);
+ netif_wake_subqueue(tun->dev, i_tfile->queue_index);
+ i_tfile->cons_cnt = 0;
+ spin_unlock(&i_tfile->tx_ring.producer_lock);
+ spin_unlock_bh(&i_tfile->tx_ring.consumer_lock);
+ }
+ }
strscpy(ifr->ifr_name, tun->dev->name);
return 0;
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 79d53c7a1ebdc5..73a77141315c7f 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -69,6 +69,7 @@
#define IFF_NAPI_FRAGS 0x0020
/* Used in TUNSETIFF to bring up tun/tap without carrier */
#define IFF_NO_CARRIER 0x0040
+#define IFF_BACKPRESSURE 0x0080
#define IFF_NO_PI 0x1000
/* This flag has no real effect */
#define IFF_ONE_QUEUE 0x2000
diff --git a/tools/include/uapi/linux/if_tun.h b/tools/include/uapi/linux/if_tun.h
index 2ec07de1d73be4..97b670f5bc0a35 100644
--- a/tools/include/uapi/linux/if_tun.h
+++ b/tools/include/uapi/linux/if_tun.h
@@ -67,6 +67,7 @@
#define IFF_TAP 0x0002
#define IFF_NAPI 0x0010
#define IFF_NAPI_FRAGS 0x0020
+#define IFF_BACKPRESSURE 0x0080
#define IFF_NO_PI 0x1000
/* This flag has no real effect */
#define IFF_ONE_QUEUE 0x2000
|
| 3/2 | 2026/07/04 11:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 3389 output: 27 thoughts: 139 Thoughts: Okay, here's my take on those thoughts, as an expert in the field: **Initial Assessment of the TUN/TAP Patch** Alright, so we've got a patch hitting my desk, and it looks like it's touching core TUN/TAP infrastructure. Specifically, I see changes to `drivers/net/tun.c`, the documentation in `tuntap.rst`, and the userspace interface header `if_tun.h`. Immediately, my spidey-sense tingles; any modification to those files has the potential for significant impact. This patch introduces a new `IFF_BACKPRESSURE` flag. This suggests a modification to how TUN/TAP interfaces handle flow control or congestion. I'm keen to understand the exact implementation changes in `tun_net_xmit`, `__tun_wake_queue`, and `tun_set_iff`. Functionality and reachability are the key considerations here. I need to understand whether this is a net-new feature, or an optimization of existing behavior. Now, let's get down to brass tacks. I've got to understand how this new feature is controlled at build time. I need to quickly identify the relevant Kconfig options. I'll need to use `grepper`, to find the config options that enable this feature. Let's see what turns up in the build system. |
| 4/2 | 2026/07/04 11:39 | tool | grepper |
0mArgs:{
"Expression": "tun\\.o",
"PathPrefix": "drivers/net/"
}Results: {
"Output": "drivers/net/Makefile=31=obj-$(CONFIG_NET_TEAM) += team/\ndrivers/net/Makefile:32:obj-$(CONFIG_TUN) += tun.o\ndrivers/net/Makefile-33-obj-$(CONFIG_TAP) += tap.o\n--\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile=41=mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += en/hv_vhca_stats.o\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile:42:mlx5_core-$(CONFIG_MLX5_ESWITCH) += lag/mp.o lag/port_sel.o lib/geneve.o lib/port_tun.o \\\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile-43-\t\t\t\t\ten_rep.o en/rep/bond.o en/mod_hdr.o \\\n--\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile=45=mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en_tc.o en/rep/tc.o en/rep/neigh.o \\\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile:46:\t\t\t\t\tlib/fs_chains.o en/tc_tun.o \\\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile-47-\t\t\t\t\tesw/indir_table.o en/tc_tun_encap.o \\\n--\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile=53=mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/act/trap.o \\\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile-54-\t\t\t\t\ten/tc/act/accept.o en/tc/act/mark.o en/tc/act/goto.o \\\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile:55:\t\t\t\t\ten/tc/act/tun.o en/tc/act/csum.o en/tc/act/pedit.o \\\ndrivers/net/ethernet/mellanox/mlx5/core/Makefile-56-\t\t\t\t\ten/tc/act/vlan.o en/tc/act/vlan_mangle.o en/tc/act/mpls.o \\\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c=1045=nfp_tunnel_lookup_offloaded_macs(struct nfp_app *app, const u8 *mac)\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1048-\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c:1049:\treturn rhashtable_lookup_fast(\u0026priv-\u003etun.offloaded_macs, mac,\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1050-\t\t\t\t offloaded_macs_params);\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c=1077=nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev,\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1127-\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c:1128:\t\tif (rhashtable_insert_fast(\u0026priv-\u003etun.offloaded_macs,\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1129-\t\t\t\t\t \u0026entry-\u003eht_node,\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1150-err_remove_hash:\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c:1151:\trhashtable_remove_fast(\u0026priv-\u003etun.offloaded_macs, \u0026entry-\u003eht_node,\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1152-\t\t\t offloaded_macs_params);\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c=1163=nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev,\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1227-\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c:1228:\tWARN_ON_ONCE(rhashtable_remove_fast(\u0026priv-\u003etun.offloaded_macs,\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1229-\t\t\t\t\t \u0026entry-\u003eht_node,\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c=1507=int nfp_tunnel_config_start(struct nfp_app *app)\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1512-\t/* Initialise rhash for MAC offload tracking. */\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c:1513:\terr = rhashtable_init(\u0026priv-\u003etun.offloaded_macs,\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1514-\t\t\t \u0026offloaded_macs_params);\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1530-\tif (err) {\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c:1531:\t\trhashtable_free_and_destroy(\u0026priv-\u003etun.offloaded_macs,\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1532-\t\t\t\t\t nfp_check_rhashtable_empty, NULL);\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c=1539=void nfp_tunnel_config_stop(struct nfp_app *app)\n--\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1558-\t/* Destroy rhash. Entries should be cleaned on netdev notifier unreg. */\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c:1559:\trhashtable_free_and_destroy(\u0026priv-\u003etun.offloaded_macs,\ndrivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c-1560-\t\t\t\t nfp_check_rhashtable_empty, NULL);\n"
} |
| 5/2 | 2026/07/04 11:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5569 output: 33 thoughts: 112 Thoughts: **Analyzing the TUN Driver Configuration** Okay, so the core configuration here is `CONFIG_TUN`, that's my starting point. Now, let's dive into the likely suspects – the heart of the TUN driver: `drivers/net/tun.c`. I need to zero in on any functions that might have been tweaked. From a quick scan, it looks like `tun_net_xmit`, `__tun_wake_queue`, and `tun_set_iff` are the ones to focus on. Hmm, are there any *other* configuration requirements floating around that could impact these functions? I should probably double-check if there's more to consider here. Right, the code is using `IFF_BACKPRESSURE` within `tun_net_xmit`, `__tun_wake_queue`, and `tun_set_iff`, that’s the crucial piece to track down. I need to see if any `#ifdef` directives are gating the use or behavior of these key functions based on specific compile-time flags. That's where the nuance often lies in this type of driver configuration. I'll need to confirm that `IFF_BACKPRESSURE` is not conditionally compiled out, and see if it is used according to its original intent. |
| 6/2 | 2026/07/04 11:39 | tool | grepper |
0mArgs:{
"Expression": "tun_net_xmit",
"PathPrefix": "drivers/net/tun.c"
}Results: {
"Output": "drivers/net/tun.c=1001=static unsigned int run_ebpf_filter(struct tun_struct *tun,\n--\ndrivers/net/tun.c-1013-/* Net device start xmit */\ndrivers/net/tun.c:1014:static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)\ndrivers/net/tun.c-1015-{\n--\ndrivers/net/tun.c=1216=static const struct net_device_ops tun_netdev_ops = {\n--\ndrivers/net/tun.c-1220-\t.ndo_stop\t\t= tun_net_close,\ndrivers/net/tun.c:1221:\t.ndo_start_xmit\t\t= tun_net_xmit,\ndrivers/net/tun.c-1222-\t.ndo_fix_features\t= tun_net_fix_features,\n--\ndrivers/net/tun.c=1300=static const struct net_device_ops tap_netdev_ops = {\n--\ndrivers/net/tun.c-1304-\t.ndo_stop\t\t= tun_net_close,\ndrivers/net/tun.c:1305:\t.ndo_start_xmit\t\t= tun_net_xmit,\ndrivers/net/tun.c-1306-\t.ndo_fix_features\t= tun_net_fix_features,\n--\ndrivers/net/tun.c=2153=static void __tun_wake_queue(struct tun_struct *tun,\n--\ndrivers/net/tun.c-2162-\ndrivers/net/tun.c:2163:\t/* Paired with smp_mb__after_atomic() in tun_net_xmit() */\ndrivers/net/tun.c-2164-\tsmp_mb();\n"
} |
| 7/2 | 2026/07/04 11:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6453 output: 33 thoughts: 135 Thoughts: **Analyzing TUN Driver Functions** Okay, so I'm looking at these functions, and the first thing I notice is that they aren't conditionally compiled with any `#ifdef` directives. That's good, less to worry about in terms of build configurations. The config is definitely set to `TUN`. I'm focused on `tun_net_xmit`, `__tun_wake_queue`, and `tun_set_iff`. Let's see... Wait a minute, `tun_net_xmit` – that's a key one! It's the `ndo_start_xmit` function, so it's very likely a hot-path function. High performance, right in the network data path. `__tun_wake_queue`... yeah, that could also be performance critical, depending on how often it's getting called. It might be in a busy loop situation. But `tun_set_iff`, nope, that's an ioctl handler. It's not going to be performance sensitive, compared to the other two. So, since I'm trying to figure out if there is a performance issue, I'm going to check the callers of `__tun_wake_queue`. I need to understand how frequently it is getting called, because there is no way to know if it is a hot-path function without context. |
| 8/2 | 2026/07/04 11:39 | tool | grepper |
0mArgs:{
"Expression": "__tun_wake_queue",
"PathPrefix": "drivers/net/tun.c"
}Results: {
"Output": "drivers/net/tun.c=1014=static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)\n--\ndrivers/net/tun.c-1084-\t\tnetif_tx_stop_queue(queue);\ndrivers/net/tun.c:1085:\t\t/* Paired with smp_mb() in __tun_wake_queue() */\ndrivers/net/tun.c-1086-\t\tsmp_mb__after_atomic();\n--\ndrivers/net/tun.c=2068=static ssize_t tun_put_user(struct tun_struct *tun,\n--\ndrivers/net/tun.c-2152-/* Callers must hold ring.consumer_lock */\ndrivers/net/tun.c:2153:static void __tun_wake_queue(struct tun_struct *tun,\ndrivers/net/tun.c-2154-\t\t\t struct tun_file *tfile, int consumed)\n--\ndrivers/net/tun.c=2175=static void *tun_ring_consume(struct tun_struct *tun, struct tun_file *tfile)\n--\ndrivers/net/tun.c-2181-\tif (ptr)\ndrivers/net/tun.c:2182:\t\t__tun_wake_queue(tun, tfile, 1);\ndrivers/net/tun.c-2183-\n--\ndrivers/net/tun.c=3829=void tun_wake_queue(struct file *file, int consumed)\n--\ndrivers/net/tun.c-3844-\tif (tun)\ndrivers/net/tun.c:3845:\t\t__tun_wake_queue(tun, tfile, consumed);\ndrivers/net/tun.c-3846-\n"
} |
| 9/2 | 2026/07/04 11:39 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7368 output: 32 thoughts: 86 Thoughts: Here's my analysis of the situation: **Investigating a Potential Bottleneck in the TUN Driver** Okay, so I'm digging into potential performance issues within the TUN driver. My current hypothesis is that there might be a bottleneck or area for optimization around `tun_wake_queue`, as it's called from both `tun_ring_consume` and, critically, from itself. `tun_ring_consume` is called during read operations, which I know is a hot path on any network interface. This makes `tun_wake_queue` and the function it calls, the place to focus my attention. Given these connections, `tun_set_iff` is likely a good symbol to concentrate on. I'll need to confirm if it's an `ioctl` operation since this is where things will likely have the biggest impact. |
| 10/2 | 2026/07/04 11:40 | tool | grepper |
0mArgs:{
"Expression": "tun_set_iff",
"PathPrefix": "drivers/net/tun.c"
}Results: {
"Output": "drivers/net/tun.c=2764=static const struct attribute_group tun_attr_group = {\n--\ndrivers/net/tun.c-2767-\ndrivers/net/tun.c:2768:static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)\ndrivers/net/tun.c-2769-{\n--\ndrivers/net/tun.c=3127=static long __tun_chr_ioctl(struct file *file, unsigned int cmd,\n--\ndrivers/net/tun.c-3174-\ndrivers/net/tun.c:3175:\t\tret = tun_set_iff(net, file, \u0026ifr);\ndrivers/net/tun.c-3176-\n"
} |
| 11/2 | 2026/07/04 11:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7864 output: 37 thoughts: 267 Thoughts: **Analyzing the `tun_set_iff` Function** Okay, so `tun_set_iff` *is* called from `__tun_chr_ioctl`, and as far as I can tell, it's definitely not a performance bottleneck. That much is clear. Let's make sure I'm not missing anything else that was modified. Okay, according to the diff, it's: `tun_net_xmit`, `__tun_wake_queue`, and `tun_set_iff`. So, it looks like `tun_set_iff` is indeed the best focus for this particular investigation. Now, let me double-check how `IFF_BACKPRESSURE` comes into play. Right, it's defined in `include/uapi/linux/if_tun.h` as `0x0080`. And it's added to `TUN_FEATURES` within `drivers/net/tun.c`. The key seems to be that `tun_set_iff` checks `tun->flags` and sets it according to the `ifr->ifr_flags`. Hang on... reading over that block of code... `tun_set_iff` actually does: ```c if (ifr->ifr_flags & IFF_BACKPRESSURE) tun->flags |= IFF_BACKPRESSURE; ``` Wait a second, the diff I saw *didn't* include `tun_set_iff` setting `IFF_BACKPRESSURE`. That's strange. Time to dive into the current implementation of `tun_set_iff` in `drivers/net/tun.c` and make sure my assumptions are correct. Something feels off here. |
| 12/2 | 2026/07/04 11:40 | tool | read-file |
0mArgs:{
"File": "drivers/net/tun.c",
"FirstLine": 2850,
"LineCount": 100
}Results: {
"Contents": "2850:\t\n2851:\t\t\tif (*ifr-\u003eifr_name)\n2852:\t\t\t\tname = ifr-\u003eifr_name;\n2853:\t\n2854:\t\t\tdev = alloc_netdev_mqs(sizeof(struct tun_struct), name,\n2855:\t\t\t\t\t NET_NAME_UNKNOWN, tun_setup, queues,\n2856:\t\t\t\t\t queues);\n2857:\t\n2858:\t\t\tif (!dev)\n2859:\t\t\t\treturn -ENOMEM;\n2860:\t\n2861:\t\t\tdev_net_set(dev, net);\n2862:\t\t\tdev-\u003ertnl_link_ops = \u0026tun_link_ops;\n2863:\t\t\tdev-\u003eifindex = tfile-\u003eifindex;\n2864:\t\t\tdev-\u003esysfs_groups[0] = \u0026tun_attr_group;\n2865:\t\n2866:\t\t\ttun = netdev_priv(dev);\n2867:\t\t\ttun-\u003edev = dev;\n2868:\t\t\ttun-\u003eflags = flags;\n2869:\t\t\ttun-\u003etxflt.count = 0;\n2870:\t\t\ttun-\u003evnet_hdr_sz = sizeof(struct virtio_net_hdr);\n2871:\t\n2872:\t\t\ttun-\u003ealign = NET_SKB_PAD;\n2873:\t\t\ttun-\u003efilter_attached = false;\n2874:\t\t\ttun-\u003esndbuf = tfile-\u003esocket.sk-\u003esk_sndbuf;\n2875:\t\t\ttun-\u003erx_batched = 0;\n2876:\t\t\tRCU_INIT_POINTER(tun-\u003esteering_prog, NULL);\n2877:\t\n2878:\t\t\ttun-\u003eifr = ifr;\n2879:\t\t\ttun-\u003efile = file;\n2880:\t\n2881:\t\t\ttun_net_initialize(dev);\n2882:\t\n2883:\t\t\terr = register_netdevice(tun-\u003edev);\n2884:\t\t\tif (err \u003c 0) {\n2885:\t\t\t\tfree_netdev(dev);\n2886:\t\t\t\treturn err;\n2887:\t\t\t}\n2888:\t\t\t/* free_netdev() won't check refcnt, to avoid race\n2889:\t\t\t * with dev_put() we need publish tun after registration.\n2890:\t\t\t */\n2891:\t\t\trcu_assign_pointer(tfile-\u003etun, tun);\n2892:\t\t}\n2893:\t\n2894:\t\tif (ifr-\u003eifr_flags \u0026 IFF_NO_CARRIER)\n2895:\t\t\tnetif_carrier_off(tun-\u003edev);\n2896:\t\telse\n2897:\t\t\tnetif_carrier_on(tun-\u003edev);\n2898:\t\n2899:\t\t/* Make sure persistent devices do not get stuck in\n2900:\t\t * xoff state.\n2901:\t\t */\n2902:\t\tif (netif_running(tun-\u003edev)) {\n2903:\t\t\tfor (int i = 0; i \u003c tun-\u003enumqueues; i++) {\n2904:\t\t\t\tstruct tun_file *i_tfile;\n2905:\t\n2906:\t\t\t\ti_tfile = rtnl_dereference(tun-\u003etfiles[i]);\n2907:\t\t\t\tspin_lock_bh(\u0026i_tfile-\u003etx_ring.consumer_lock);\n2908:\t\t\t\tspin_lock(\u0026i_tfile-\u003etx_ring.producer_lock);\n2909:\t\t\t\tnetif_wake_subqueue(tun-\u003edev, i_tfile-\u003equeue_index);\n2910:\t\t\t\ti_tfile-\u003econs_cnt = 0;\n2911:\t\t\t\tspin_unlock(\u0026i_tfile-\u003etx_ring.producer_lock);\n2912:\t\t\t\tspin_unlock_bh(\u0026i_tfile-\u003etx_ring.consumer_lock);\n2913:\t\t\t}\n2914:\t\t}\n2915:\t\n2916:\t\tstrscpy(ifr-\u003eifr_name, tun-\u003edev-\u003ename);\n2917:\t\treturn 0;\n2918:\t}\n2919:\t\n2920:\tstatic void tun_get_iff(struct tun_struct *tun, struct ifreq *ifr)\n2921:\t{\n2922:\t\tstrscpy(ifr-\u003eifr_name, tun-\u003edev-\u003ename);\n2923:\t\n2924:\t\tifr-\u003eifr_flags = tun_flags(tun);\n2925:\t\n2926:\t}\n2927:\t\n2928:\t#define PLAIN_GSO (NETIF_F_GSO_UDP_L4 | NETIF_F_TSO | NETIF_F_TSO6)\n2929:\t\n2930:\t/* This is like a cut-down ethtool ops, except done via tun fd so no\n2931:\t * privs required. */\n2932:\tstatic int set_offload(struct tun_struct *tun, unsigned long arg)\n2933:\t{\n2934:\t\tnetdev_features_t features = 0;\n2935:\t\n2936:\t\tif (arg \u0026 TUN_F_CSUM) {\n2937:\t\t\tfeatures |= NETIF_F_HW_CSUM;\n2938:\t\t\targ \u0026= ~TUN_F_CSUM;\n2939:\t\n2940:\t\t\tif (arg \u0026 (TUN_F_TSO4|TUN_F_TSO6)) {\n2941:\t\t\t\tif (arg \u0026 TUN_F_TSO_ECN) {\n2942:\t\t\t\t\tfeatures |= NETIF_F_TSO_ECN;\n2943:\t\t\t\t\targ \u0026= ~TUN_F_TSO_ECN;\n2944:\t\t\t\t}\n2945:\t\t\t\tif (arg \u0026 TUN_F_TSO4)\n2946:\t\t\t\t\tfeatures |= NETIF_F_TSO;\n2947:\t\t\t\tif (arg \u0026 TUN_F_TSO6)\n2948:\t\t\t\t\tfeatures |= NETIF_F_TSO6;\n2949:\t\t\t\targ \u0026= ~(TUN_F_TSO4|TUN_F_TSO6);\n"
} |
| 13/2 | 2026/07/04 11:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10115 output: 37 thoughts: 43 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Analyzing the Tunnel Interface Flag Assignment** Right, so I'm looking at `tun->flags = flags;` specifically where that `flags` value comes from in the context of the tunnel device setup. The focus is on how those flags are ultimately derived from `ifr->ifr_flags`. I need to fully understand how these flags are being copied, altered, or even masked during the interface configuration process, which is handled in the `tun_set_iff` function. I want to track precisely what settings are actually making it onto the tunnel interface. Are there any potential bitwise manipulations happening? Any unexpected side effects? I'm particularly interested in any modifications relative to the initial user-specified interface flags – how are they being translated, or if any standard flags are getting implicitly added or removed? Essentially, I need to know the complete transformation process to ensure the correct behavior of the tunnel. |
| 14/2 | 2026/07/04 11:40 | tool | read-file |
0mArgs:{
"File": "drivers/net/tun.c",
"FirstLine": 2768,
"LineCount": 100
}Results: {
"Contents": "2768:\tstatic int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)\n2769:\t{\n2770:\t\tstruct tun_struct *tun;\n2771:\t\tstruct tun_file *tfile = file-\u003eprivate_data;\n2772:\t\tstruct net_device *dev;\n2773:\t\tint err;\n2774:\t\n2775:\t\tif (tfile-\u003edetached)\n2776:\t\t\treturn -EINVAL;\n2777:\t\n2778:\t\tif ((ifr-\u003eifr_flags \u0026 IFF_NAPI_FRAGS)) {\n2779:\t\t\tif (!capable(CAP_NET_ADMIN))\n2780:\t\t\t\treturn -EPERM;\n2781:\t\n2782:\t\t\tif (!(ifr-\u003eifr_flags \u0026 IFF_NAPI) ||\n2783:\t\t\t (ifr-\u003eifr_flags \u0026 TUN_TYPE_MASK) != IFF_TAP)\n2784:\t\t\t\treturn -EINVAL;\n2785:\t\t}\n2786:\t\n2787:\t\tdev = __dev_get_by_name(net, ifr-\u003eifr_name);\n2788:\t\tif (dev) {\n2789:\t\t\tif (ifr-\u003eifr_flags \u0026 IFF_TUN_EXCL)\n2790:\t\t\t\treturn -EBUSY;\n2791:\t\t\tif ((ifr-\u003eifr_flags \u0026 IFF_TUN) \u0026\u0026 dev-\u003enetdev_ops == \u0026tun_netdev_ops)\n2792:\t\t\t\ttun = netdev_priv(dev);\n2793:\t\t\telse if ((ifr-\u003eifr_flags \u0026 IFF_TAP) \u0026\u0026 dev-\u003enetdev_ops == \u0026tap_netdev_ops)\n2794:\t\t\t\ttun = netdev_priv(dev);\n2795:\t\t\telse\n2796:\t\t\t\treturn -EINVAL;\n2797:\t\n2798:\t\t\tif (!!(ifr-\u003eifr_flags \u0026 IFF_MULTI_QUEUE) !=\n2799:\t\t\t !!(tun-\u003eflags \u0026 IFF_MULTI_QUEUE))\n2800:\t\t\t\treturn -EINVAL;\n2801:\t\n2802:\t\t\tif (tun_not_capable(tun))\n2803:\t\t\t\treturn -EPERM;\n2804:\t\t\terr = security_tun_dev_open(tun-\u003esecurity);\n2805:\t\t\tif (err \u003c 0)\n2806:\t\t\t\treturn err;\n2807:\t\n2808:\t\t\terr = tun_attach(tun, file, ifr-\u003eifr_flags \u0026 IFF_NOFILTER,\n2809:\t\t\t\t\t ifr-\u003eifr_flags \u0026 IFF_NAPI,\n2810:\t\t\t\t\t ifr-\u003eifr_flags \u0026 IFF_NAPI_FRAGS, true);\n2811:\t\t\tif (err \u003c 0)\n2812:\t\t\t\treturn err;\n2813:\t\n2814:\t\t\tif (tun-\u003eflags \u0026 IFF_MULTI_QUEUE \u0026\u0026\n2815:\t\t\t (tun-\u003enumqueues + tun-\u003enumdisabled \u003e 1)) {\n2816:\t\t\t\t/* One or more queue has already been attached, no need\n2817:\t\t\t\t * to initialize the device again.\n2818:\t\t\t\t */\n2819:\t\t\t\tnetdev_state_change(dev);\n2820:\t\t\t\treturn 0;\n2821:\t\t\t}\n2822:\t\n2823:\t\t\ttun-\u003eflags = (tun-\u003eflags \u0026 ~TUN_FEATURES) |\n2824:\t\t\t\t (ifr-\u003eifr_flags \u0026 TUN_FEATURES);\n2825:\t\n2826:\t\t\tnetdev_state_change(dev);\n2827:\t\t} else {\n2828:\t\t\tchar *name;\n2829:\t\t\tunsigned long flags = 0;\n2830:\t\t\tint queues = ifr-\u003eifr_flags \u0026 IFF_MULTI_QUEUE ?\n2831:\t\t\t\t MAX_TAP_QUEUES : 1;\n2832:\t\n2833:\t\t\tif (!ns_capable(net-\u003euser_ns, CAP_NET_ADMIN))\n2834:\t\t\t\treturn -EPERM;\n2835:\t\t\terr = security_tun_dev_create();\n2836:\t\t\tif (err \u003c 0)\n2837:\t\t\t\treturn err;\n2838:\t\n2839:\t\t\t/* Set dev type */\n2840:\t\t\tif (ifr-\u003eifr_flags \u0026 IFF_TUN) {\n2841:\t\t\t\t/* TUN device */\n2842:\t\t\t\tflags |= IFF_TUN;\n2843:\t\t\t\tname = \"tun%d\";\n2844:\t\t\t} else if (ifr-\u003eifr_flags \u0026 IFF_TAP) {\n2845:\t\t\t\t/* TAP device */\n2846:\t\t\t\tflags |= IFF_TAP;\n2847:\t\t\t\tname = \"tap%d\";\n2848:\t\t\t} else\n2849:\t\t\t\treturn -EINVAL;\n2850:\t\n2851:\t\t\tif (*ifr-\u003eifr_name)\n2852:\t\t\t\tname = ifr-\u003eifr_name;\n2853:\t\n2854:\t\t\tdev = alloc_netdev_mqs(sizeof(struct tun_struct), name,\n2855:\t\t\t\t\t NET_NAME_UNKNOWN, tun_setup, queues,\n2856:\t\t\t\t\t queues);\n2857:\t\n2858:\t\t\tif (!dev)\n2859:\t\t\t\treturn -ENOMEM;\n2860:\t\n2861:\t\t\tdev_net_set(dev, net);\n2862:\t\t\tdev-\u003ertnl_link_ops = \u0026tun_link_ops;\n2863:\t\t\tdev-\u003eifindex = tfile-\u003eifindex;\n2864:\t\t\tdev-\u003esysfs_groups[0] = \u0026tun_attr_group;\n2865:\t\n2866:\t\t\ttun = netdev_priv(dev);\n2867:\t\t\ttun-\u003edev = dev;\n"
} |
| 15/2 | 2026/07/04 11:40 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11923 output: 108 thoughts: 440 Thoughts: **My Analysis of the TUN/TAP Backpressure Patch** Okay, let's break this down. That line, `tun->flags = (tun->flags & ~TUN_FEATURES) | (ifr->ifr_flags & TUN_FEATURES);` and the inclusion of `IFF_BACKPRESSURE` into `TUN_FEATURES` is key. So, `tun_set_iff` handles the setting of this flag, which seems to be the entry point for the backpressure functionality. The crucial point is that this patch changes how the TUN device handles a full ring buffer. Instead of packet drops, it introduces backpressure via the IFF_BACKPRESSURE flag, stopping the TX queue. I need to figure out the best way to fuzz this. My initial thought was `tun_net_xmit`, since that's where the backpressure logic is *executed*. However, that function is in the hot path, so I should avoid it. `tun_set_iff`, being an `ioctl` handler, is a much better target for Syzkaller's fuzzing capabilities. It's the point of *setting* the flag, a cleaner entry point. I also considered `__tun_wake_queue`, but that's called from `tun_ring_consume`, which in turn is called from `tun_do_read`, so that's also in a hot path. Therefore, I'm sticking with `tun_set_iff`. That's the best focus symbol. Now, config dependencies. From what I can tell, `CONFIG_TUN` is the only requirement, as `drivers/net/tun.c` is compiled when `CONFIG_TUN` is set. No other configs are needed. The header sync in `tools/include/uapi/linux/if_tun.h` is just that – a header sync; no logic is really there. Okay, let's summarize my findings: * WorthFuzzing: `true` * FocusSymbols: `["tun_set_iff"]` * EnableConfigs: `["TUN"]` * Reasoning: "The patch introduces a new IFF_BACKPRESSURE flag for TUN/TAP devices, modifying the behavior of `tun_net_xmit` and `__tun_wake_queue` to stop the TX queue instead of dropping packets when the ring buffer is full. This is a functional change that can be reached via the TUNSETIFF ioctl." I think that covers it. Time to call `set-results`. |
| 16/2 | 2026/07/04 11:40 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"TUN"
],
"FocusSymbols": [
"tun_set_iff"
],
"Reasoning": "The patch introduces a new IFF_BACKPRESSURE flag for TUN/TAP devices, modifying the behavior of tun_net_xmit and __tun_wake_queue to stop the TX queue instead of dropping packets when the ring buffer is full. This is a functional change that can be reached via the TUNSETIFF ioctl.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"TUN"
],
"FocusSymbols": [
"tun_set_iff"
],
"Reasoning": "The patch introduces a new IFF_BACKPRESSURE flag for TUN/TAP devices, modifying the behavior of tun_net_xmit and __tun_wake_queue to stop the TX queue instead of dropping packets when the ring buffer is full. This is a functional change that can be reached via the TUNSETIFF ioctl.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|