| From cca8ea3b05c972ffb5295367e6c544369b45fbdd Mon Sep 17 00:00:00 2001 |
| From: Phillip Potter <phil@philpotter.co.uk> |
| Date: Tue, 6 Apr 2021 18:45:54 +0100 |
| Subject: net: tun: set tun->dev->addr_len during TUNSETLINK processing |
| |
| From: Phillip Potter <phil@philpotter.co.uk> |
| |
| commit cca8ea3b05c972ffb5295367e6c544369b45fbdd upstream. |
| |
| When changing type with TUNSETLINK ioctl command, set tun->dev->addr_len |
| to match the appropriate type, using new tun_get_addr_len utility function |
| which returns appropriate address length for given type. Fixes a |
| KMSAN-found uninit-value bug reported by syzbot at: |
| https://syzkaller.appspot.com/bug?id=0766d38c656abeace60621896d705743aeefed51 |
| |
| Reported-by: syzbot+001516d86dbe88862cec@syzkaller.appspotmail.com |
| Diagnosed-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: Phillip Potter <phil@philpotter.co.uk> |
| Reviewed-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/tun.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 48 insertions(+) |
| |
| --- a/drivers/net/tun.c |
| +++ b/drivers/net/tun.c |
| @@ -71,6 +71,14 @@ |
| #include <net/sock.h> |
| #include <linux/seq_file.h> |
| #include <linux/uio.h> |
| +#include <linux/ieee802154.h> |
| +#include <linux/if_ltalk.h> |
| +#include <uapi/linux/if_fddi.h> |
| +#include <uapi/linux/if_hippi.h> |
| +#include <uapi/linux/if_fc.h> |
| +#include <net/ax25.h> |
| +#include <net/rose.h> |
| +#include <net/6lowpan.h> |
| |
| #include <asm/uaccess.h> |
| |
| @@ -1888,6 +1896,45 @@ unlock: |
| return ret; |
| } |
| |
| +/* Return correct value for tun->dev->addr_len based on tun->dev->type. */ |
| +static unsigned char tun_get_addr_len(unsigned short type) |
| +{ |
| + switch (type) { |
| + case ARPHRD_IP6GRE: |
| + case ARPHRD_TUNNEL6: |
| + return sizeof(struct in6_addr); |
| + case ARPHRD_IPGRE: |
| + case ARPHRD_TUNNEL: |
| + case ARPHRD_SIT: |
| + return 4; |
| + case ARPHRD_ETHER: |
| + return ETH_ALEN; |
| + case ARPHRD_IEEE802154: |
| + case ARPHRD_IEEE802154_MONITOR: |
| + return IEEE802154_EXTENDED_ADDR_LEN; |
| + case ARPHRD_PHONET_PIPE: |
| + case ARPHRD_PPP: |
| + case ARPHRD_NONE: |
| + return 0; |
| + case ARPHRD_6LOWPAN: |
| + return EUI64_ADDR_LEN; |
| + case ARPHRD_FDDI: |
| + return FDDI_K_ALEN; |
| + case ARPHRD_HIPPI: |
| + return HIPPI_ALEN; |
| + case ARPHRD_IEEE802: |
| + return FC_ALEN; |
| + case ARPHRD_ROSE: |
| + return ROSE_ADDR_LEN; |
| + case ARPHRD_NETROM: |
| + return AX25_ADDR_LEN; |
| + case ARPHRD_LOCALTLK: |
| + return LTALK_ALEN; |
| + default: |
| + return 0; |
| + } |
| +} |
| + |
| static long __tun_chr_ioctl(struct file *file, unsigned int cmd, |
| unsigned long arg, int ifreq_len) |
| { |
| @@ -2026,6 +2073,7 @@ static long __tun_chr_ioctl(struct file |
| ret = -EBUSY; |
| } else { |
| tun->dev->type = (int) arg; |
| + tun->dev->addr_len = tun_get_addr_len(tun->dev->type); |
| tun_debug(KERN_INFO, tun, "linktype set to %d\n", |
| tun->dev->type); |
| ret = 0; |