aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_flowlabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_flowlabel.c')
-rw-r--r--net/ipv6/ip6_flowlabel.c80
1 files changed, 22 insertions, 58 deletions
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 29124b7a04c..54303945019 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -21,8 +21,6 @@
21#include <linux/proc_fs.h> 21#include <linux/proc_fs.h>
22#include <linux/seq_file.h> 22#include <linux/seq_file.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/export.h>
25#include <linux/pid_namespace.h>
26 24
27#include <net/net_namespace.h> 25#include <net/net_namespace.h>
28#include <net/sock.h> 26#include <net/sock.h>
@@ -92,8 +90,6 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label)
92static void fl_free(struct ip6_flowlabel *fl) 90static void fl_free(struct ip6_flowlabel *fl)
93{ 91{
94 if (fl) { 92 if (fl) {
95 if (fl->share == IPV6_FL_S_PROCESS)
96 put_pid(fl->owner.pid);
97 release_net(fl->fl_net); 93 release_net(fl->fl_net);
98 kfree(fl->opt); 94 kfree(fl->opt);
99 } 95 }
@@ -297,7 +293,6 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
297 opt_space->opt_flen = fopt->opt_flen; 293 opt_space->opt_flen = fopt->opt_flen;
298 return opt_space; 294 return opt_space;
299} 295}
300EXPORT_SYMBOL_GPL(fl6_merge_options);
301 296
302static unsigned long check_linger(unsigned long ttl) 297static unsigned long check_linger(unsigned long ttl)
303{ 298{
@@ -390,17 +385,17 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
390 err = -EINVAL; 385 err = -EINVAL;
391 goto done; 386 goto done;
392 } 387 }
393 fl->dst = freq->flr_dst; 388 ipv6_addr_copy(&fl->dst, &freq->flr_dst);
394 atomic_set(&fl->users, 1); 389 atomic_set(&fl->users, 1);
395 switch (fl->share) { 390 switch (fl->share) {
396 case IPV6_FL_S_EXCL: 391 case IPV6_FL_S_EXCL:
397 case IPV6_FL_S_ANY: 392 case IPV6_FL_S_ANY:
398 break; 393 break;
399 case IPV6_FL_S_PROCESS: 394 case IPV6_FL_S_PROCESS:
400 fl->owner.pid = get_task_pid(current, PIDTYPE_PID); 395 fl->owner = current->pid;
401 break; 396 break;
402 case IPV6_FL_S_USER: 397 case IPV6_FL_S_USER:
403 fl->owner.uid = current_euid(); 398 fl->owner = current_euid();
404 break; 399 break;
405 default: 400 default:
406 err = -EINVAL; 401 err = -EINVAL;
@@ -436,32 +431,32 @@ static int mem_check(struct sock *sk)
436 return 0; 431 return 0;
437} 432}
438 433
439static bool ipv6_hdr_cmp(struct ipv6_opt_hdr *h1, struct ipv6_opt_hdr *h2) 434static int ipv6_hdr_cmp(struct ipv6_opt_hdr *h1, struct ipv6_opt_hdr *h2)
440{ 435{
441 if (h1 == h2) 436 if (h1 == h2)
442 return false; 437 return 0;
443 if (h1 == NULL || h2 == NULL) 438 if (h1 == NULL || h2 == NULL)
444 return true; 439 return 1;
445 if (h1->hdrlen != h2->hdrlen) 440 if (h1->hdrlen != h2->hdrlen)
446 return true; 441 return 1;
447 return memcmp(h1+1, h2+1, ((h1->hdrlen+1)<<3) - sizeof(*h1)); 442 return memcmp(h1+1, h2+1, ((h1->hdrlen+1)<<3) - sizeof(*h1));
448} 443}
449 444
450static bool ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2) 445static int ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2)
451{ 446{
452 if (o1 == o2) 447 if (o1 == o2)
453 return false; 448 return 0;
454 if (o1 == NULL || o2 == NULL) 449 if (o1 == NULL || o2 == NULL)
455 return true; 450 return 1;
456 if (o1->opt_nflen != o2->opt_nflen) 451 if (o1->opt_nflen != o2->opt_nflen)
457 return true; 452 return 1;
458 if (ipv6_hdr_cmp(o1->hopopt, o2->hopopt)) 453 if (ipv6_hdr_cmp(o1->hopopt, o2->hopopt))
459 return true; 454 return 1;
460 if (ipv6_hdr_cmp(o1->dst0opt, o2->dst0opt)) 455 if (ipv6_hdr_cmp(o1->dst0opt, o2->dst0opt))
461 return true; 456 return 1;
462 if (ipv6_hdr_cmp((struct ipv6_opt_hdr *)o1->srcrt, (struct ipv6_opt_hdr *)o2->srcrt)) 457 if (ipv6_hdr_cmp((struct ipv6_opt_hdr *)o1->srcrt, (struct ipv6_opt_hdr *)o2->srcrt))
463 return true; 458 return 1;
464 return false; 459 return 0;
465} 460}
466 461
467static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl, 462static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl,
@@ -519,8 +514,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
519 } 514 }
520 read_unlock_bh(&ip6_sk_fl_lock); 515 read_unlock_bh(&ip6_sk_fl_lock);
521 516
522 if (freq.flr_share == IPV6_FL_S_NONE && 517 if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
523 ns_capable(net->user_ns, CAP_NET_ADMIN)) {
524 fl = fl_lookup(net, freq.flr_label); 518 fl = fl_lookup(net, freq.flr_label);
525 if (fl) { 519 if (fl) {
526 err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); 520 err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
@@ -565,10 +559,7 @@ recheck:
565 err = -EPERM; 559 err = -EPERM;
566 if (fl1->share == IPV6_FL_S_EXCL || 560 if (fl1->share == IPV6_FL_S_EXCL ||
567 fl1->share != fl->share || 561 fl1->share != fl->share ||
568 ((fl1->share == IPV6_FL_S_PROCESS) && 562 fl1->owner != fl->owner)
569 (fl1->owner.pid == fl->owner.pid)) ||
570 ((fl1->share == IPV6_FL_S_USER) &&
571 uid_eq(fl1->owner.uid, fl->owner.uid)))
572 goto release; 563 goto release;
573 564
574 err = -EINVAL; 565 err = -EINVAL;
@@ -628,7 +619,6 @@ done:
628 619
629struct ip6fl_iter_state { 620struct ip6fl_iter_state {
630 struct seq_net_private p; 621 struct seq_net_private p;
631 struct pid_namespace *pid_ns;
632 int bucket; 622 int bucket;
633}; 623};
634 624
@@ -707,7 +697,6 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
707 697
708static int ip6fl_seq_show(struct seq_file *seq, void *v) 698static int ip6fl_seq_show(struct seq_file *seq, void *v)
709{ 699{
710 struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
711 if (v == SEQ_START_TOKEN) 700 if (v == SEQ_START_TOKEN)
712 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", 701 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
713 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); 702 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
@@ -715,13 +704,9 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v)
715 struct ip6_flowlabel *fl = v; 704 struct ip6_flowlabel *fl = v;
716 seq_printf(seq, 705 seq_printf(seq,
717 "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", 706 "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n",
718 (unsigned int)ntohl(fl->label), 707 (unsigned)ntohl(fl->label),
719 fl->share, 708 fl->share,
720 ((fl->share == IPV6_FL_S_PROCESS) ? 709 (unsigned)fl->owner,
721 pid_nr_ns(fl->owner.pid, state->pid_ns) :
722 ((fl->share == IPV6_FL_S_USER) ?
723 from_kuid_munged(seq_user_ns(seq), fl->owner.uid) :
724 0)),
725 atomic_read(&fl->users), 710 atomic_read(&fl->users),
726 fl->linger/HZ, 711 fl->linger/HZ,
727 (long)(fl->expires - jiffies)/HZ, 712 (long)(fl->expires - jiffies)/HZ,
@@ -740,29 +725,8 @@ static const struct seq_operations ip6fl_seq_ops = {
740 725
741static int ip6fl_seq_open(struct inode *inode, struct file *file) 726static int ip6fl_seq_open(struct inode *inode, struct file *file)
742{ 727{
743 struct seq_file *seq; 728 return seq_open_net(inode, file, &ip6fl_seq_ops,
744 struct ip6fl_iter_state *state; 729 sizeof(struct ip6fl_iter_state));
745 int err;
746
747 err = seq_open_net(inode, file, &ip6fl_seq_ops,
748 sizeof(struct ip6fl_iter_state));
749
750 if (!err) {
751 seq = file->private_data;
752 state = ip6fl_seq_private(seq);
753 rcu_read_lock();
754 state->pid_ns = get_pid_ns(task_active_pid_ns(current));
755 rcu_read_unlock();
756 }
757 return err;
758}
759
760static int ip6fl_seq_release(struct inode *inode, struct file *file)
761{
762 struct seq_file *seq = file->private_data;
763 struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
764 put_pid_ns(state->pid_ns);
765 return seq_release_net(inode, file);
766} 730}
767 731
768static const struct file_operations ip6fl_seq_fops = { 732static const struct file_operations ip6fl_seq_fops = {
@@ -770,7 +734,7 @@ static const struct file_operations ip6fl_seq_fops = {
770 .open = ip6fl_seq_open, 734 .open = ip6fl_seq_open,
771 .read = seq_read, 735 .read = seq_read,
772 .llseek = seq_lseek, 736 .llseek = seq_lseek,
773 .release = ip6fl_seq_release, 737 .release = seq_release_net,
774}; 738};
775 739
776static int __net_init ip6_flowlabel_proc_init(struct net *net) 740static int __net_init ip6_flowlabel_proc_init(struct net *net)