aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r--net/ipv4/raw.c17
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;
646back_from_confirm: 653back_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