diff options
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r-- | net/ipv4/raw.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 33b70bfd1122..5e570aa9e43b 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -513,11 +513,18 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
513 | int err; | 513 | int err; |
514 | struct ip_options_data opt_copy; | 514 | struct ip_options_data opt_copy; |
515 | struct raw_frag_vec rfv; | 515 | struct raw_frag_vec rfv; |
516 | int hdrincl; | ||
516 | 517 | ||
517 | err = -EMSGSIZE; | 518 | err = -EMSGSIZE; |
518 | if (len > 0xFFFF) | 519 | if (len > 0xFFFF) |
519 | goto out; | 520 | goto out; |
520 | 521 | ||
522 | /* hdrincl should be READ_ONCE(inet->hdrincl) | ||
523 | * but READ_ONCE() doesn't work with bit fields. | ||
524 | * Doing this indirectly yields the same result. | ||
525 | */ | ||
526 | hdrincl = inet->hdrincl; | ||
527 | hdrincl = READ_ONCE(hdrincl); | ||
521 | /* | 528 | /* |
522 | * Check the flags. | 529 | * Check the flags. |
523 | */ | 530 | */ |
@@ -593,7 +600,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
593 | /* Linux does not mangle headers on raw sockets, | 600 | /* Linux does not mangle headers on raw sockets, |
594 | * so that IP options + IP_HDRINCL is non-sense. | 601 | * so that IP options + IP_HDRINCL is non-sense. |
595 | */ | 602 | */ |
596 | if (inet->hdrincl) | 603 | if (hdrincl) |
597 | goto done; | 604 | goto done; |
598 | if (ipc.opt->opt.srr) { | 605 | if (ipc.opt->opt.srr) { |
599 | if (!daddr) | 606 | if (!daddr) |
@@ -615,12 +622,12 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
615 | 622 | ||
616 | flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, | 623 | flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, |
617 | RT_SCOPE_UNIVERSE, | 624 | RT_SCOPE_UNIVERSE, |
618 | inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, | 625 | hdrincl ? IPPROTO_RAW : sk->sk_protocol, |
619 | inet_sk_flowi_flags(sk) | | 626 | inet_sk_flowi_flags(sk) | |
620 | (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), | 627 | (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), |
621 | daddr, saddr, 0, 0, sk->sk_uid); | 628 | daddr, saddr, 0, 0, sk->sk_uid); |
622 | 629 | ||
623 | if (!inet->hdrincl) { | 630 | if (!hdrincl) { |
624 | rfv.msg = msg; | 631 | rfv.msg = msg; |
625 | rfv.hlen = 0; | 632 | rfv.hlen = 0; |
626 | 633 | ||
@@ -645,7 +652,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
645 | goto do_confirm; | 652 | goto do_confirm; |
646 | back_from_confirm: | 653 | back_from_confirm: |
647 | 654 | ||
648 | if (inet->hdrincl) | 655 | if (hdrincl) |
649 | err = raw_send_hdrinc(sk, &fl4, msg, len, | 656 | err = raw_send_hdrinc(sk, &fl4, msg, len, |
650 | &rt, msg->msg_flags, &ipc.sockc); | 657 | &rt, msg->msg_flags, &ipc.sockc); |
651 | 658 | ||