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.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 9772fbd8a3f5..90bbefb57943 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>
@@ -91,6 +92,8 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label)
91static void fl_free(struct ip6_flowlabel *fl) 92static void fl_free(struct ip6_flowlabel *fl)
92{ 93{
93 if (fl) { 94 if (fl) {
95 if (fl->share == IPV6_FL_S_PROCESS)
96 put_pid(fl->owner.pid);
94 release_net(fl->fl_net); 97 release_net(fl->fl_net);
95 kfree(fl->opt); 98 kfree(fl->opt);
96 } 99 }
@@ -394,10 +397,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
394 case IPV6_FL_S_ANY: 397 case IPV6_FL_S_ANY:
395 break; 398 break;
396 case IPV6_FL_S_PROCESS: 399 case IPV6_FL_S_PROCESS:
397 fl->owner = current->pid; 400 fl->owner.pid = get_task_pid(current, PIDTYPE_PID);
398 break; 401 break;
399 case IPV6_FL_S_USER: 402 case IPV6_FL_S_USER:
400 fl->owner = current_euid(); 403 fl->owner.uid = current_euid();
401 break; 404 break;
402 default: 405 default:
403 err = -EINVAL; 406 err = -EINVAL;
@@ -561,7 +564,10 @@ recheck:
561 err = -EPERM; 564 err = -EPERM;
562 if (fl1->share == IPV6_FL_S_EXCL || 565 if (fl1->share == IPV6_FL_S_EXCL ||
563 fl1->share != fl->share || 566 fl1->share != fl->share ||
564 fl1->owner != fl->owner) 567 ((fl1->share == IPV6_FL_S_PROCESS) &&
568 (fl1->owner.pid == fl->owner.pid)) ||
569 ((fl1->share == IPV6_FL_S_USER) &&
570 uid_eq(fl1->owner.uid, fl->owner.uid)))
565 goto release; 571 goto release;
566 572
567 err = -EINVAL; 573 err = -EINVAL;
@@ -621,6 +627,7 @@ done:
621 627
622struct ip6fl_iter_state { 628struct ip6fl_iter_state {
623 struct seq_net_private p; 629 struct seq_net_private p;
630 struct pid_namespace *pid_ns;
624 int bucket; 631 int bucket;
625}; 632};
626 633
@@ -699,6 +706,7 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
699 706
700static int ip6fl_seq_show(struct seq_file *seq, void *v) 707static int ip6fl_seq_show(struct seq_file *seq, void *v)
701{ 708{
709 struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
702 if (v == SEQ_START_TOKEN) 710 if (v == SEQ_START_TOKEN)
703 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", 711 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
704 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); 712 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
@@ -708,7 +716,11 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v)
708 "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", 716 "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n",
709 (unsigned int)ntohl(fl->label), 717 (unsigned int)ntohl(fl->label),
710 fl->share, 718 fl->share,
711 (int)fl->owner, 719 ((fl->share == IPV6_FL_S_PROCESS) ?
720 pid_nr_ns(fl->owner.pid, state->pid_ns) :
721 ((fl->share == IPV6_FL_S_USER) ?
722 from_kuid_munged(seq_user_ns(seq), fl->owner.uid) :
723 0)),
712 atomic_read(&fl->users), 724 atomic_read(&fl->users),
713 fl->linger/HZ, 725 fl->linger/HZ,
714 (long)(fl->expires - jiffies)/HZ, 726 (long)(fl->expires - jiffies)/HZ,
@@ -727,8 +739,29 @@ static const struct seq_operations ip6fl_seq_ops = {
727 739
728static int ip6fl_seq_open(struct inode *inode, struct file *file) 740static int ip6fl_seq_open(struct inode *inode, struct file *file)
729{ 741{
730 return seq_open_net(inode, file, &ip6fl_seq_ops, 742 struct seq_file *seq;
731 sizeof(struct ip6fl_iter_state)); 743 struct ip6fl_iter_state *state;
744 int err;
745
746 err = seq_open_net(inode, file, &ip6fl_seq_ops,
747 sizeof(struct ip6fl_iter_state));
748
749 if (!err) {
750 seq = file->private_data;
751 state = ip6fl_seq_private(seq);
752 rcu_read_lock();
753 state->pid_ns = get_pid_ns(task_active_pid_ns(current));
754 rcu_read_unlock();
755 }
756 return err;
757}
758
759static int ip6fl_seq_release(struct inode *inode, struct file *file)
760{
761 struct seq_file *seq = file->private_data;
762 struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
763 put_pid_ns(state->pid_ns);
764 return seq_release_net(inode, file);
732} 765}
733 766
734static const struct file_operations ip6fl_seq_fops = { 767static const struct file_operations ip6fl_seq_fops = {
@@ -736,7 +769,7 @@ static const struct file_operations ip6fl_seq_fops = {
736 .open = ip6fl_seq_open, 769 .open = ip6fl_seq_open,
737 .read = seq_read, 770 .read = seq_read,
738 .llseek = seq_lseek, 771 .llseek = seq_lseek,
739 .release = seq_release_net, 772 .release = ip6fl_seq_release,
740}; 773};
741 774
742static int __net_init ip6_flowlabel_proc_init(struct net *net) 775static int __net_init ip6_flowlabel_proc_init(struct net *net)