[PATCH bpf v2 1/3] bpf: Pin iterator link when opening iterator

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Hou Tao <houtao1@xxxxxxxxxx>

For many bpf iterator (e.g., cgroup iterator), iterator link acquires
the reference of iteration target in .attach_target(), but iterator link
may be closed before or in the middle of iteration, so iterator will
need to acquire the reference of iteration target as well to prevent
potential use-after-free. To avoid doing the acquisition in
.init_seq_private() for each iterator type, just pin iterator link in
iterator.

Fixes: d4ccaf58a847 ("bpf: Introduce cgroup iter")
Signed-off-by: Hou Tao <houtao1@xxxxxxxxxx>
---
 kernel/bpf/bpf_iter.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c
index 5dc307bdeaeb..67d899011cb2 100644
--- a/kernel/bpf/bpf_iter.c
+++ b/kernel/bpf/bpf_iter.c
@@ -20,7 +20,7 @@ struct bpf_iter_link {
 };
 
 struct bpf_iter_priv_data {
-	struct bpf_iter_target_info *tinfo;
+	struct bpf_iter_link *link;
 	const struct bpf_iter_seq_info *seq_info;
 	struct bpf_prog *prog;
 	u64 session_id;
@@ -79,7 +79,7 @@ static bool bpf_iter_support_resched(struct seq_file *seq)
 
 	iter_priv = container_of(seq->private, struct bpf_iter_priv_data,
 				 target_private);
-	return bpf_iter_target_support_resched(iter_priv->tinfo);
+	return bpf_iter_target_support_resched(iter_priv->link->tinfo);
 }
 
 /* maximum visited objects before bailing out */
@@ -276,6 +276,7 @@ static int iter_release(struct inode *inode, struct file *file)
 		iter_priv->seq_info->fini_seq_private(seq->private);
 
 	bpf_prog_put(iter_priv->prog);
+	bpf_link_put(&iter_priv->link->link);
 	seq->private = iter_priv;
 
 	return seq_release_private(inode, file);
@@ -576,11 +577,19 @@ int bpf_iter_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
 }
 
 static void init_seq_meta(struct bpf_iter_priv_data *priv_data,
-			  struct bpf_iter_target_info *tinfo,
+			  struct bpf_iter_link *link,
 			  const struct bpf_iter_seq_info *seq_info,
 			  struct bpf_prog *prog)
 {
-	priv_data->tinfo = tinfo;
+	/* For many bpf iterator, iterator link acquires the reference of
+	 * iteration target in .attach_target(), but iterator link may be
+	 * closed before or in the middle of iteration, so iterator will
+	 * need to acquire the reference of iteration target as well. To
+	 * avoid doing the acquisition in .init_seq_private() for each
+	 * iterator type, just pin iterator link in iterator.
+	 */
+	bpf_link_inc(&link->link);
+	priv_data->link = link;
 	priv_data->seq_info = seq_info;
 	priv_data->prog = prog;
 	priv_data->session_id = atomic64_inc_return(&session_id);
@@ -592,7 +601,6 @@ static int prepare_seq_file(struct file *file, struct bpf_iter_link *link,
 			    const struct bpf_iter_seq_info *seq_info)
 {
 	struct bpf_iter_priv_data *priv_data;
-	struct bpf_iter_target_info *tinfo;
 	struct bpf_prog *prog;
 	u32 total_priv_dsize;
 	struct seq_file *seq;
@@ -603,7 +611,6 @@ static int prepare_seq_file(struct file *file, struct bpf_iter_link *link,
 	bpf_prog_inc(prog);
 	mutex_unlock(&link_mutex);
 
-	tinfo = link->tinfo;
 	total_priv_dsize = offsetof(struct bpf_iter_priv_data, target_private) +
 			   seq_info->seq_priv_size;
 	priv_data = __seq_open_private(file, seq_info->seq_ops,
@@ -619,7 +626,7 @@ static int prepare_seq_file(struct file *file, struct bpf_iter_link *link,
 			goto release_seq_file;
 	}
 
-	init_seq_meta(priv_data, tinfo, seq_info, prog);
+	init_seq_meta(priv_data, link, seq_info, prog);
 	seq = file->private_data;
 	seq->private = priv_data->target_private;
 
-- 
2.29.2




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux