* [PATCH net] net: vlan: fix vlan name truncation
@ 2026-09-04 21:00 Janis Edvarts Lacis
0 siblings, 0 replies; only message in thread
From: Janis Edvarts Lacis @ 2026-09-04 21:00 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, kuba, pabeni, horms, linux-kernel,
Janis Edvarts Lacis
register_vlan_device() from net/8021q/vlan.c sets name based on a field
name_type from struct vlan_net. If name_type is VLAN_NAME_TYPE_RAW_PLUS_VID
or VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, register_vlan_device() sets vlan
device's name to the actual net_device's name and adds vid at the end of
this name separated by a dot.
Network interface's name is limited to at most 16 characters, including NUL.
Therefore, if the real_dev->name is long enough, then adding the vid
at the end of this name can lead to the result exceeding 16 bytes which
leads to a truncated name for the vlan device created in register_vlan_device().
This patch fixes the issue by returning -ENAMETOOLONG from
register_vlan_device() if the newly created name does not fit in 16
bytes.
The bug was discovered when compiling with flag W=1, the following warning comes up:
linux/net/8021q/vlan.c: In function ‘vlan_ioctl_handler’:
linux/net/8021q/vlan.c:250:46: error: ‘%i’ directive output may be truncated writing between 1 and 5 bytes into a region of size between 0 and 15 [-Werror=format-truncation=]
250 | snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
| ^~
In function ‘register_vlan_device’,
inlined from ‘vlan_ioctl_handler’ at linux/net/8021q/vlan.c:588:9:
linux/net/8021q/vlan.c:250:42: note: directive argument in the range [0, 65535]
250 | snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
| ^~~~~~~
Build & run the reproducer:
gcc poc.c -o poc
chmod +x poc.sh
./poc.sh
======BEGIN poc.sh======
#!/usr/bin/env bash
sudo ip link add vlan1234567890 type dummy
sudo ./poc
# name will not match the expected printed from poc.c on the unpatched
# kernel, there will be no vlan interface at all on the patched one
ip a
======END poc.sh========
======BEGIN poc.c======
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/sockios.h>
#define IF_NAME "vlan1234567890"
int main()
{
struct vlan_ioctl_args args = {
.cmd = ADD_VLAN_CMD,
.u.VID = 1234,
};
strcpy(args.device1, IF_NAME);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return 1;
}
/* fails with -ENAMETOOLONG */
if (ioctl(fd, SIOCSIFVLAN, &args) < 0) {
perror("SIOCSIFVLAN");
close(fd);
return 1;
}
printf("Expected name: %s.%i\n", IF_NAME, args.u.VID);
close(fd);
return 0;
}
======END poc.c========
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Janis Edvarts Lacis <janislacis06@gmail.com>
---
net/8021q/vlan.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 2d2efb877975..b51092d217de 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -220,7 +220,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
struct net *net = dev_net(real_dev);
struct vlan_net *vn = net_generic(net, vlan_net_id);
char name[IFNAMSIZ];
- int err;
+ int err, len;
if (vlan_id >= VLAN_VID_MASK)
return -ERANGE;
@@ -234,7 +234,9 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
switch (vn->name_type) {
case VLAN_NAME_TYPE_RAW_PLUS_VID:
/* name will look like: eth1.0005 */
- snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
+ len = snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
+ if (len >= sizeof(name))
+ err = -ENAMETOOLONG;
break;
case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:
/* Put our vlan.VID in the name.
@@ -246,7 +248,9 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
/* Put our vlan.VID in the name.
* Name will look like: eth0.5
*/
- snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
+ len = snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
+ if (len >= sizeof(name))
+ err = -ENAMETOOLONG;
break;
case VLAN_NAME_TYPE_PLUS_VID:
/* Put our vlan.VID in the name.
@@ -256,6 +260,9 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
}
+ if (err)
+ return err;
+
new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name,
NET_NAME_UNKNOWN, vlan_setup);
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-04 21:00 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-04 21:00 [PATCH net] net: vlan: fix vlan name truncation Janis Edvarts Lacis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox