diff options
-rw-r--r-- | include/net/ipv6.h | 5 | ||||
-rw-r--r-- | init/Kconfig | 1 | ||||
-rw-r--r-- | kernel/pid.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 50 |
4 files changed, 48 insertions, 9 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 01c34b363a34..c8a202436e01 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -222,7 +222,10 @@ struct ip6_flowlabel { | |||
222 | struct ipv6_txoptions *opt; | 222 | struct ipv6_txoptions *opt; |
223 | unsigned long linger; | 223 | unsigned long linger; |
224 | u8 share; | 224 | u8 share; |
225 | u32 owner; | 225 | union { |
226 | struct pid *pid; | ||
227 | kuid_t uid; | ||
228 | } owner; | ||
226 | unsigned long lastuse; | 229 | unsigned long lastuse; |
227 | unsigned long expires; | 230 | unsigned long expires; |
228 | struct net *fl_net; | 231 | struct net *fl_net; |
diff --git a/init/Kconfig b/init/Kconfig index f857f97bcef3..64ff9ce59443 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -948,7 +948,6 @@ config UIDGID_CONVERTED | |||
948 | depends on NETFILTER_XT_MATCH_RECENT = n | 948 | depends on NETFILTER_XT_MATCH_RECENT = n |
949 | depends on NETFILTER_XT_TARGET_LOG = n | 949 | depends on NETFILTER_XT_TARGET_LOG = n |
950 | depends on NETFILTER_NETLINK_LOG = n | 950 | depends on NETFILTER_NETLINK_LOG = n |
951 | depends on IPV6 = n | ||
952 | depends on AF_RXRPC = n | 951 | depends on AF_RXRPC = n |
953 | depends on NET_KEY = n | 952 | depends on NET_KEY = n |
954 | depends on INET_DIAG = n | 953 | depends on INET_DIAG = n |
diff --git a/kernel/pid.c b/kernel/pid.c index e86b291ad834..aebd4f5aaf41 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -479,6 +479,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns) | |||
479 | } | 479 | } |
480 | return nr; | 480 | return nr; |
481 | } | 481 | } |
482 | EXPORT_SYMBOL_GPL(pid_nr_ns); | ||
482 | 483 | ||
483 | pid_t pid_vnr(struct pid *pid) | 484 | pid_t pid_vnr(struct pid *pid) |
484 | { | 485 | { |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 9772fbd8a3f5..c836a6a20a34 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -22,6 +22,7 @@ | |||
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> | 24 | #include <linux/export.h> |
25 | #include <linux/pid_namespace.h> | ||
25 | 26 | ||
26 | #include <net/net_namespace.h> | 27 | #include <net/net_namespace.h> |
27 | #include <net/sock.h> | 28 | #include <net/sock.h> |
@@ -90,6 +91,11 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label) | |||
90 | 91 | ||
91 | static void fl_free(struct ip6_flowlabel *fl) | 92 | static void fl_free(struct ip6_flowlabel *fl) |
92 | { | 93 | { |
94 | switch (fl->share) { | ||
95 | case IPV6_FL_S_PROCESS: | ||
96 | put_pid(fl->owner.pid); | ||
97 | break; | ||
98 | } | ||
93 | if (fl) { | 99 | if (fl) { |
94 | release_net(fl->fl_net); | 100 | release_net(fl->fl_net); |
95 | kfree(fl->opt); | 101 | kfree(fl->opt); |
@@ -394,10 +400,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, | |||
394 | case IPV6_FL_S_ANY: | 400 | case IPV6_FL_S_ANY: |
395 | break; | 401 | break; |
396 | case IPV6_FL_S_PROCESS: | 402 | case IPV6_FL_S_PROCESS: |
397 | fl->owner = current->pid; | 403 | fl->owner.pid = get_task_pid(current, PIDTYPE_PID); |
398 | break; | 404 | break; |
399 | case IPV6_FL_S_USER: | 405 | case IPV6_FL_S_USER: |
400 | fl->owner = current_euid(); | 406 | fl->owner.uid = current_euid(); |
401 | break; | 407 | break; |
402 | default: | 408 | default: |
403 | err = -EINVAL; | 409 | err = -EINVAL; |
@@ -561,7 +567,10 @@ recheck: | |||
561 | err = -EPERM; | 567 | err = -EPERM; |
562 | if (fl1->share == IPV6_FL_S_EXCL || | 568 | if (fl1->share == IPV6_FL_S_EXCL || |
563 | fl1->share != fl->share || | 569 | fl1->share != fl->share || |
564 | fl1->owner != fl->owner) | 570 | ((fl1->share == IPV6_FL_S_PROCESS) && |
571 | (fl1->owner.pid == fl->owner.pid)) || | ||
572 | ((fl1->share == IPV6_FL_S_USER) && | ||
573 | uid_eq(fl1->owner.uid, fl->owner.uid))) | ||
565 | goto release; | 574 | goto release; |
566 | 575 | ||
567 | err = -EINVAL; | 576 | err = -EINVAL; |
@@ -621,6 +630,7 @@ done: | |||
621 | 630 | ||
622 | struct ip6fl_iter_state { | 631 | struct ip6fl_iter_state { |
623 | struct seq_net_private p; | 632 | struct seq_net_private p; |
633 | struct pid_namespace *pid_ns; | ||
624 | int bucket; | 634 | int bucket; |
625 | }; | 635 | }; |
626 | 636 | ||
@@ -699,6 +709,7 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v) | |||
699 | 709 | ||
700 | static int ip6fl_seq_show(struct seq_file *seq, void *v) | 710 | static int ip6fl_seq_show(struct seq_file *seq, void *v) |
701 | { | 711 | { |
712 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | ||
702 | if (v == SEQ_START_TOKEN) | 713 | if (v == SEQ_START_TOKEN) |
703 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", | 714 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", |
704 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); | 715 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); |
@@ -708,7 +719,11 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v) | |||
708 | "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", | 719 | "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", |
709 | (unsigned int)ntohl(fl->label), | 720 | (unsigned int)ntohl(fl->label), |
710 | fl->share, | 721 | fl->share, |
711 | (int)fl->owner, | 722 | ((fl->share == IPV6_FL_S_PROCESS) ? |
723 | pid_nr_ns(fl->owner.pid, state->pid_ns) : | ||
724 | ((fl->share == IPV6_FL_S_USER) ? | ||
725 | from_kuid_munged(seq_user_ns(seq), fl->owner.uid) : | ||
726 | 0)), | ||
712 | atomic_read(&fl->users), | 727 | atomic_read(&fl->users), |
713 | fl->linger/HZ, | 728 | fl->linger/HZ, |
714 | (long)(fl->expires - jiffies)/HZ, | 729 | (long)(fl->expires - jiffies)/HZ, |
@@ -727,8 +742,29 @@ static const struct seq_operations ip6fl_seq_ops = { | |||
727 | 742 | ||
728 | static int ip6fl_seq_open(struct inode *inode, struct file *file) | 743 | static int ip6fl_seq_open(struct inode *inode, struct file *file) |
729 | { | 744 | { |
730 | return seq_open_net(inode, file, &ip6fl_seq_ops, | 745 | struct seq_file *seq; |
731 | sizeof(struct ip6fl_iter_state)); | 746 | struct ip6fl_iter_state *state; |
747 | int err; | ||
748 | |||
749 | err = seq_open_net(inode, file, &ip6fl_seq_ops, | ||
750 | sizeof(struct ip6fl_iter_state)); | ||
751 | |||
752 | if (!err) { | ||
753 | seq = file->private_data; | ||
754 | state = ip6fl_seq_private(seq); | ||
755 | rcu_read_lock(); | ||
756 | state->pid_ns = get_pid_ns(task_active_pid_ns(current)); | ||
757 | rcu_read_unlock(); | ||
758 | } | ||
759 | return err; | ||
760 | } | ||
761 | |||
762 | static int ip6fl_seq_release(struct inode *inode, struct file *file) | ||
763 | { | ||
764 | struct seq_file *seq = file->private_data; | ||
765 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | ||
766 | put_pid_ns(state->pid_ns); | ||
767 | return seq_release_net(inode, file); | ||
732 | } | 768 | } |
733 | 769 | ||
734 | static const struct file_operations ip6fl_seq_fops = { | 770 | static const struct file_operations ip6fl_seq_fops = { |
@@ -736,7 +772,7 @@ static const struct file_operations ip6fl_seq_fops = { | |||
736 | .open = ip6fl_seq_open, | 772 | .open = ip6fl_seq_open, |
737 | .read = seq_read, | 773 | .read = seq_read, |
738 | .llseek = seq_lseek, | 774 | .llseek = seq_lseek, |
739 | .release = seq_release_net, | 775 | .release = ip6fl_seq_release, |
740 | }; | 776 | }; |
741 | 777 | ||
742 | static int __net_init ip6_flowlabel_proc_init(struct net *net) | 778 | static int __net_init ip6_flowlabel_proc_init(struct net *net) |