Jann Horn
7e5a206ab6
tcp: don't read out-of-bounds opsize
The old code reads the "opsize" variable from out-of-bounds memory (first
byte behind the segment) if a broken TCP segment ends directly after an
opcode that is neither EOL nor NOP.
The result of the read isn't used for anything, so the worst thing that
could theoretically happen is a pagefault; and since the physmap is usually
mostly contiguous, even that seems pretty unlikely.
The following C reproducer triggers the uninitialized read - however, you
can't actually see anything happen unless you put something like a
pr_warn() in tcp_parse_md5sig_option() to print the opsize.
====================================
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/in.h>
#include <linux/if_tun.h>
#include <err.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>
void systemf(const char *command, ...) {
char *full_command;
va_list ap;
va_start(ap, command);
if (vasprintf(&full_command, command, ap) == -1)
err(1, "vasprintf");
va_end(ap);
printf("systemf: <<<%s>>>\n", full_command);
system(full_command);
}
char *devname;
int tun_alloc(char *name) {
int fd = open("/dev/net/tun", O_RDWR);
if (fd == -1)
err(1, "open tun dev");
static struct ifreq req = { .ifr_flags = IFF_TUN|IFF_NO_PI };
strcpy(req.ifr_name, name);
if (ioctl(fd, TUNSETIFF, &req))
err(1, "TUNSETIFF");
devname = req.ifr_name;
printf("device name: %s\n", devname);
return fd;
}
#define IPADDR(a,b,c,d) (((a)<<0)+((b)<<8)+((c)<<16)+((d)<<24))
void sum_accumulate(unsigned int *sum, void *data, int len) {
assert((len&2)==0);
for (int i=0; i<len/2; i++) {
*sum += ntohs(((unsigned short *)data)[i]);
}
}
unsigned short sum_final(unsigned int sum) {
sum = (sum >> 16) + (sum & 0xffff);
sum = (sum >> 16) + (sum & 0xffff);
return htons(~sum);
}
void fix_ip_sum(struct iphdr *ip) {
unsigned int sum = 0;
sum_accumulate(&sum, ip, sizeof(*ip));
ip->check = sum_final(sum);
}
void fix_tcp_sum(struct iphdr *ip, struct tcphdr *tcp) {
unsigned int sum = 0;
struct {
unsigned int saddr;
unsigned int daddr;
unsigned char pad;
unsigned char proto_num;
unsigned short tcp_len;
} fakehdr = {
.saddr = ip->saddr,
.daddr = ip->daddr,
.proto_num = ip->protocol,
.tcp_len = htons(ntohs(ip->tot_len) - ip->ihl*4)
};
sum_accumulate(&sum, &fakehdr, sizeof(fakehdr));
sum_accumulate(&sum, tcp, tcp->doff*4);
tcp->check = sum_final(sum);
}
int main(void) {
int tun_fd = tun_alloc("inject_dev%d");
systemf("ip link set %s up", devname);
systemf("ip addr add 192.168.42.1/24 dev %s", devname);
struct {
struct iphdr ip;
struct tcphdr tcp;
unsigned char tcp_opts[20];
} __attribute__((packed)) syn_packet = {
.ip = {
.ihl = sizeof(struct iphdr)/4,
.version = 4,
.tot_len = htons(sizeof(syn_packet)),
.ttl = 30,
.protocol = IPPROTO_TCP,
/* FIXUP check */
.saddr = IPADDR(192,168,42,2),
.daddr = IPADDR(192,168,42,1)
},
.tcp = {
.source = htons(1),
.dest = htons(1337),
.seq = 0x12345678,
.doff = (sizeof(syn_packet.tcp)+sizeof(syn_packet.tcp_opts))/4,
.syn = 1,
.window = htons(64),
.check = 0 /*FIXUP*/
},
.tcp_opts = {
/* INVALID: trailing MD5SIG opcode after NOPs */
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 19
}
};
fix_ip_sum(&syn_packet.ip);
fix_tcp_sum(&syn_packet.ip, &syn_packet.tcp);
while (1) {
int write_res = write(tun_fd, &syn_packet, sizeof(syn_packet));
if (write_res != sizeof(syn_packet))
err(1, "packet write failed");
}
}
====================================
Fixes: cfb6eeb4c8 ("[TCP]: MD5 Signature Option (RFC2385) support.")
Signed-off-by: Jann Horn <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
|
2018-04-23 09:51:06 -04:00 |
| .. |
|
netfilter
|
kbuild: rename *-asn1.[ch] to *.asn1.[ch]
|
2018-04-07 19:04:02 +09:00 |
|
af_inet.c
|
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
|
2018-03-31 23:33:04 -04:00 |
|
ah4.c
|
net: use -ENOSPC for transient busy indication
|
2017-11-03 22:11:17 +08:00 |
|
arp.c
|
arp: fix arp_filter on l3slave devices
|
2018-04-05 22:05:03 -04:00 |
|
cipso_ipv4.c
|
tcp/dccp: fix ireq->opt races
|
2017-10-21 01:33:19 +01:00 |
|
datagram.c
|
|
|
|
devinet.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
esp4.c
|
esp4: remove redundant initialization of pointer esph
|
2018-02-13 13:59:03 +01:00 |
|
esp4_offload.c
|
esp: check the NETIF_F_HW_ESP_TX_CSUM bit before segmenting
|
2018-02-27 10:46:01 +01:00 |
|
fib_frontend.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
fib_lookup.h
|
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
|
2017-11-02 11:10:55 +01:00 |
|
fib_notifier.c
|
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
|
2017-11-02 11:10:55 +01:00 |
|
fib_rules.c
|
ipv6: route: dissect flow in input path if fib rules need it
|
2018-02-28 22:44:44 -05:00 |
|
fib_semantics.c
|
route: check sysctl_fib_multipath_use_neigh earlier than hash
|
2018-04-01 20:57:39 -04:00 |
|
fib_trie.c
|
net/ipv4: Allow notifier to fail route replace
|
2018-03-29 14:10:30 -04:00 |
|
fou.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
gre_demux.c
|
|
|
|
gre_offload.c
|
gso: fix payload length when gso_size is zero
|
2017-10-08 10:12:15 -07:00 |
|
icmp.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
igmp.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
inet_connection_sock.c
|
Revert "defer call to mem_cgroup_sk_alloc()"
|
2018-02-02 19:49:31 -05:00 |
|
inet_diag.c
|
sock_diag: request _diag module only when the family or proto has been registered
|
2018-03-12 11:03:42 -04:00 |
|
inet_fragment.c
|
inet: frags: remove inet_frag_maybe_warn_overflow()
|
2018-03-31 23:25:39 -04:00 |
|
inet_hashtables.c
|
inet: Avoid unitialized variable warning in inet_unhash()
|
2018-02-01 09:48:42 -05:00 |
|
inet_timewait_sock.c
|
soreuseport: initialise timewait reuseport field
|
2018-04-07 22:32:32 -04:00 |
|
inetpeer.c
|
inetpeer: fix uninit-value in inet_getpeer
|
2018-04-09 10:57:35 -04:00 |
|
ip_forward.c
|
net: rename skb_gso_validate_mtu -> skb_gso_validate_network_len
|
2018-03-04 17:49:17 -05:00 |
|
ip_fragment.c
|
inet: frags: fix ip6frag_low_thresh boundary
|
2018-04-04 12:04:59 -04:00 |
|
ip_gre.c
|
ip_gre: clear feature flags when incompatible o_flags are set
|
2018-04-10 11:03:32 -04:00 |
|
ip_input.c
|
net: Make ip_ra_chain per struct net
|
2018-03-22 15:12:56 -04:00 |
|
ip_options.c
|
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
|
2017-11-02 11:10:55 +01:00 |
|
ip_output.c
|
net: Fix one possible memleak in ip_setup_cork
|
2018-04-16 12:57:06 -04:00 |
|
ip_sockglue.c
|
net: Replace ip_ra_lock with per-net mutex
|
2018-03-22 15:12:56 -04:00 |
|
ip_tunnel.c
|
ip_tunnel: better validate user provided tunnel names
|
2018-04-05 15:16:15 -04:00 |
|
ip_tunnel_core.c
|
|
|
|
ip_vti.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
ipcomp.c
|
|
|
|
ipconfig.c
|
net: Use octal not symbolic permissions
|
2018-03-26 12:07:48 -04:00 |
|
ipip.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
ipmr.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
ipmr_base.c
|
ipmr: Make ipmr_dump() common
|
2018-03-26 13:14:43 -04:00 |
|
Kconfig
|
ipmr,ipmr6: Define a uniform vif_device
|
2018-03-01 13:13:23 -05:00 |
|
Makefile
|
ipmr,ipmr6: Define a uniform vif_device
|
2018-03-01 13:13:23 -05:00 |
|
netfilter.c
|
netfilter: remove struct nf_afinfo and its helper functions
|
2018-01-08 18:11:02 +01:00 |
|
ping.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
proc.c
|
inet: frags: break the 2GB limit for frags storage
|
2018-03-31 23:25:39 -04:00 |
|
protocol.c
|
|
|
|
raw.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
raw_diag.c
|
|
|
|
route.c
|
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
|
2018-04-09 17:04:10 -07:00 |
|
syncookies.c
|
net/ipv4: disable SMC TCP option with SYN Cookies
|
2018-03-25 20:53:54 -04:00 |
|
sysctl_net_ipv4.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
tcp.c
|
tcp: clear tp->packets_out when purging write queue
|
2018-04-16 11:23:42 -04:00 |
|
tcp_bbr.c
|
net-tcp_bbr: set tp->snd_ssthresh to BDP upon STARTUP exit
|
2018-03-16 15:07:48 -04:00 |
|
tcp_bic.c
|
|
|
|
tcp_cdg.c
|
tcp: cdg: make struct tcp_cdg static
|
2017-10-16 21:24:25 +01:00 |
|
tcp_cong.c
|
tcp: Namespace-ify sysctl_tcp_default_congestion_control
|
2017-11-15 14:09:52 +09:00 |
|
tcp_cubic.c
|
|
|
|
tcp_dctcp.c
|
|
|
|
tcp_diag.c
|
net: sock: replace sk_state_load with inet_sk_state_load and remove sk_state_store
|
2017-12-20 14:00:25 -05:00 |
|
tcp_fastopen.c
|
tcp: pause Fast Open globally after third consecutive timeout
|
2017-12-13 15:51:12 -05:00 |
|
tcp_highspeed.c
|
|
|
|
tcp_htcp.c
|
|
|
|
tcp_hybla.c
|
|
|
|
tcp_illinois.c
|
net/tcp/illinois: replace broken algorithm reference link
|
2018-02-28 12:03:47 -05:00 |
|
tcp_input.c
|
tcp: don't read out-of-bounds opsize
|
2018-04-23 09:51:06 -04:00 |
|
tcp_ipv4.c
|
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
|
2018-03-31 23:33:04 -04:00 |
|
tcp_lp.c
|
|
|
|
tcp_metrics.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
tcp_minisocks.c
|
crypto : chtls - CPL handler definition
|
2018-03-31 23:37:32 -04:00 |
|
tcp_nv.c
|
tcp_nv: fix potential integer overflow in tcpnv_acked
|
2018-01-31 10:26:30 -05:00 |
|
tcp_offload.c
|
gso: validate gso_type in GSO handlers
|
2018-01-22 16:01:30 -05:00 |
|
tcp_output.c
|
tcp_bbr: better deal with suboptimal GSO (II)
|
2018-03-01 21:44:28 -05:00 |
|
tcp_rate.c
|
tcp: invalidate rate samples during SACK reneging
|
2017-12-08 10:07:02 -05:00 |
|
tcp_recovery.c
|
tcp: evaluate packet losses upon RTT change
|
2017-12-08 14:14:11 -05:00 |
|
tcp_scalable.c
|
|
|
|
tcp_timer.c
|
tcp: purge write queue upon aborting the connection
|
2018-03-07 15:01:03 -05:00 |
|
tcp_ulp.c
|
net: add a UID to use for ULP socket assignment
|
2018-02-06 11:39:31 +01:00 |
|
tcp_vegas.c
|
|
|
|
tcp_vegas.h
|
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
|
2017-11-02 11:10:55 +01:00 |
|
tcp_veno.c
|
|
|
|
tcp_westwood.c
|
|
|
|
tcp_yeah.c
|
|
|
|
tunnel4.c
|
inet: whitespace cleanup
|
2018-02-28 11:43:28 -05:00 |
|
udp.c
|
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
|
2018-03-31 23:33:04 -04:00 |
|
udp_diag.c
|
|
|
|
udp_impl.h
|
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
|
2017-11-02 11:10:55 +01:00 |
|
udp_offload.c
|
gso: validate gso_type in GSO handlers
|
2018-01-22 16:01:30 -05:00 |
|
udp_tunnel.c
|
|
|
|
udplite.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
xfrm4_input.c
|
xfrm: Reinject transport-mode packets through tasklet
|
2017-12-19 08:23:21 +01:00 |
|
xfrm4_mode_beet.c
|
|
|
|
xfrm4_mode_transport.c
|
|
|
|
xfrm4_mode_tunnel.c
|
xfrm: Verify MAC header exists before overwriting eth_hdr(skb)->h_proto
|
2018-03-07 10:54:29 +01:00 |
|
xfrm4_output.c
|
net: xfrm: use skb_gso_validate_network_len() to check gso sizes
|
2018-03-04 17:49:17 -05:00 |
|
xfrm4_policy.c
|
net: Drop pernet_operations::async
|
2018-03-27 13:18:09 -04:00 |
|
xfrm4_protocol.c
|
|
|
|
xfrm4_state.c
|
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
|
2017-11-02 11:10:55 +01:00 |
|
xfrm4_tunnel.c
|
|
|