Commit 89d7ae34cdda4195809a5a987f697a517a2a3177
Committed by
David S. Miller
1 parent
a018540141
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
cipso: don't follow a NULL pointer when setsockopt() is called
As reported by Alan Cox, and verified by Lin Ming, when a user attempts to add a CIPSO option to a socket using the CIPSO_V4_TAG_LOCAL tag the kernel dies a terrible death when it attempts to follow a NULL pointer (the skb argument to cipso_v4_validate() is NULL when called via the setsockopt() syscall). This patch fixes this by first checking to ensure that the skb is non-NULL before using it to find the incoming network interface. In the unlikely case where the skb is NULL and the user attempts to add a CIPSO option with the _TAG_LOCAL tag we return an error as this is not something we want to allow. A simple reproducer, kindly supplied by Lin Ming, although you must have the CIPSO DOI #3 configure on the system first or you will be caught early in cipso_v4_validate(): #include <sys/types.h> #include <sys/socket.h> #include <linux/ip.h> #include <linux/in.h> #include <string.h> struct local_tag { char type; char length; char info[4]; }; struct cipso { char type; char length; char doi[4]; struct local_tag local; }; int main(int argc, char **argv) { int sockfd; struct cipso cipso = { .type = IPOPT_CIPSO, .length = sizeof(struct cipso), .local = { .type = 128, .length = sizeof(struct local_tag), }, }; memset(cipso.doi, 0, 4); cipso.doi[3] = 3; sockfd = socket(AF_INET, SOCK_DGRAM, 0); #define SOL_IP 0 setsockopt(sockfd, SOL_IP, IP_OPTIONS, &cipso, sizeof(struct cipso)); return 0; } CC: Lin Ming <mlin@ss.pku.edu.cn> Reported-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Paul Moore <pmoore@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 4 additions and 2 deletions Side-by-side Diff
net/ipv4/cipso_ipv4.c
... | ... | @@ -1725,8 +1725,10 @@ |
1725 | 1725 | case CIPSO_V4_TAG_LOCAL: |
1726 | 1726 | /* This is a non-standard tag that we only allow for |
1727 | 1727 | * local connections, so if the incoming interface is |
1728 | - * not the loopback device drop the packet. */ | |
1729 | - if (!(skb->dev->flags & IFF_LOOPBACK)) { | |
1728 | + * not the loopback device drop the packet. Further, | |
1729 | + * there is no legitimate reason for setting this from | |
1730 | + * userspace so reject it if skb is NULL. */ | |
1731 | + if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) { | |
1730 | 1732 | err_offset = opt_iter; |
1731 | 1733 | goto validate_return_locked; |
1732 | 1734 | } |