aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-05-24 12:37:59 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-08-15 00:49:25 -0400
commit4f82f45730c68fdaf9b0472495a965188404866e (patch)
tree81b32f29328766a5fc3213c00e4177e0cfbedd40 /net
parent7064d16e162adf8199f0288b694e6af823ed5431 (diff)
net ip6 flowlabel: Make owner a union of struct pid * and kuid_t
Correct a long standing omission and use struct pid in the owner field of struct ip6_flowlabel when the share type is IPV6_FL_S_PROCESS. This guarantees we don't have issues when pid wraparound occurs. Use a kuid_t in the owner field of struct ip6_flowlabel when the share type is IPV6_FL_S_USER to add user namespace support. In /proc/net/ip6_flowlabel capture the current pid namespace when opening the file and release the pid namespace when the file is closed ensuring we print the pid owner value that is meaning to the reader of the file. Similarly use from_kuid_munged to print uid values that are meaningful to the reader of the file. This requires exporting pid_nr_ns so that ipv6 can continue to built as a module. Yoiks what silliness Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/ip6_flowlabel.c50
1 files changed, 43 insertions, 7 deletions
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
91static void fl_free(struct ip6_flowlabel *fl) 92static 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
622struct ip6fl_iter_state { 631struct 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
700static int ip6fl_seq_show(struct seq_file *seq, void *v) 710static 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
728static int ip6fl_seq_open(struct inode *inode, struct file *file) 743static 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
762static 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
734static const struct file_operations ip6fl_seq_fops = { 770static 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
742static int __net_init ip6_flowlabel_proc_init(struct net *net) 778static int __net_init ip6_flowlabel_proc_init(struct net *net)