lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Thu, 23 Apr 2020 20:50:39 -0700
From:   Andrii Nakryiko <andriin@...com>
To:     <bpf@...r.kernel.org>, <netdev@...r.kernel.org>, <ast@...com>,
        <daniel@...earbox.net>
CC:     <andrii.nakryiko@...il.com>, <kernel-team@...com>,
        Andrii Nakryiko <andriin@...com>
Subject: [PATCH bpf] bpf: fix leak in LINK_UPDATE and enforce empty old_prog_fd

Fix bug of not putting bpf_link in LINK_UPDATE command.
Also enforce zeroed old_prog_fd if no BPF_F_REPLACE flag is specified.

Signed-off-by: Andrii Nakryiko <andriin@...com>
---
 kernel/bpf/syscall.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index d85f37239540..087cf27218c9 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -3608,7 +3608,7 @@ static int link_create(union bpf_attr *attr)
 
 static int link_update(union bpf_attr *attr)
 {
-	struct bpf_prog *old_prog = NULL, *new_prog;
+	struct bpf_prog *old_prog = NULL, *new_prog = NULL;
 	struct bpf_link *link;
 	u32 flags;
 	int ret;
@@ -3628,31 +3628,38 @@ static int link_update(union bpf_attr *attr)
 		return PTR_ERR(link);
 
 	new_prog = bpf_prog_get(attr->link_update.new_prog_fd);
-	if (IS_ERR(new_prog))
-		return PTR_ERR(new_prog);
+	if (IS_ERR(new_prog)) {
+		ret = PTR_ERR(new_prog);
+		new_prog = NULL;
+		goto out_put;
+	}
 
 	if (flags & BPF_F_REPLACE) {
 		old_prog = bpf_prog_get(attr->link_update.old_prog_fd);
 		if (IS_ERR(old_prog)) {
 			ret = PTR_ERR(old_prog);
 			old_prog = NULL;
-			goto out_put_progs;
+			goto out_put;
 		}
+	} else if (attr->link_update.old_prog_fd) {
+		ret = -EINVAL;
+		goto out_put;
 	}
 
 #ifdef CONFIG_CGROUP_BPF
 	if (link->ops == &bpf_cgroup_link_lops) {
 		ret = cgroup_bpf_replace(link, old_prog, new_prog);
-		goto out_put_progs;
+		goto out_put;
 	}
 #endif
 	ret = -EINVAL;
 
-out_put_progs:
+out_put:
 	if (old_prog)
 		bpf_prog_put(old_prog);
-	if (ret)
+	if (ret && new_prog)
 		bpf_prog_put(new_prog);
+	bpf_link_put(link);
 	return ret;
 }
 
-- 
2.24.1

Powered by blists - more mailing lists