bpf: link: refuse non-O_RDWR flags in BPF_OBJ_GET
Subsystems (3)
PATCH v2 1/2 bpf: link: refuse non-O_RDWR flags in BPF_OBJ_GET
Invoking BPF_OBJ_GET on a pinned bpf_link checks the path access permissions based on file_flags, but the returned fd ignores flags. This means that any user can acquire a "read-write" fd for a pinned link with mode 0664 by invoking BPF_OBJ_GET with BPF_F_RDONLY in file_flags. The fd can be used to invoke BPF_LINK_DETACH, etc.
Fix this by refusing non-O_RDWR flags in BPF_OBJ_GET. This works because OBJ_GET by default returns a read write mapping and libbpf doesn't expose a way to override this behaviour for programs and links.
--- kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/inode.c +1 -1
@@ -547,7 +547,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags)else if (type ==BPF_TYPE_MAP ) ret =bpf_map_new_fd (raw, f_flags);else if (type ==BPF_TYPE_LINK ) - ret =bpf_link_new_fd (raw); + ret = (f_flags !=O_RDWR ) ? -EINVAL :bpf_link_new_fd (raw);else return -ENOENT ;
Signature · 1 line
2.27.0
PATCH v2 2/2 bpf: program: refuse non-O_RDWR flags in BPF_OBJ_GET
As for bpf_link, refuse creating a non-O_RDWR fd. Since program fds currently don't allow modifications this is a precaution, not a straight up bug fix.
--- kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/inode.c +1 -1
@@ -543,7 +543,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags)return PTR_ERR (raw);if (type ==BPF_TYPE_PROG ) - ret =bpf_prog_new_fd (raw); + ret = (f_flags !=O_RDWR ) ? -EINVAL :bpf_prog_new_fd (raw);else if (type ==BPF_TYPE_MAP ) ret =bpf_map_new_fd (raw, f_flags);else if (type ==BPF_TYPE_LINK )
Signature · 1 line
2.27.0
Song Liu
reviewerRe: [PATCH bpf v2 2/2] bpf: program: refuse non-O_RDWR flags in BPF_OBJ_GET
Quoted 15 lines · Lorenz Bauer
As for
bpf_link, refuse creating a non-O_RDWR fd. Since program fds currently don't allow modifications this is a precaution, not a straight up bug fix.Signed-off-by Lorenz Bauer <[email protected]>--- kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)kernel/bpf/inode.c +0
-0
kernel/bpf/inode.c int bpf_obj_get_user(const char __user *pathname, int flags) · line 543
Quoted 1 line
kernel/bpf/inode.c +0
-0@@ -543,7 +543,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags)return PTR_ERR (raw);
For both patches, shall we do the check before bpf_obj_do_get(), which is a few lines above?
Thanks,
Song
Quoted 10 lines
kernel/bpf/inode.c +1
-2if (type ==BPF_TYPE_PROG ) - ret =bpf_prog_new_fd (raw); + ret = (f_flags !=O_RDWR ) ? -EINVAL :bpf_prog_new_fd (raw);else if (type ==BPF_TYPE_MAP ) ret =bpf_map_new_fd (raw, f_flags);else if (type ==BPF_TYPE_LINK ) --2.27.0
Andrii Nakryiko
Acked-byRe: [PATCH bpf v2 2/2] bpf: program: refuse non-O_RDWR flags in BPF_OBJ_GET
Quoted 12 lines · Song Liu
Quoted 10 lines · Lorenz Bauer
As for
bpf_link, refuse creating a non-O_RDWR fd. Since program fds currently don't allow modifications this is a precaution, not a straight up bug fix.Signed-off-by Lorenz Bauer <[email protected]>--- kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Quoted 9 lines
kernel/bpf/inode.c int bpf_obj_get_user(const char __user *pathname, int flags) · line 543
Quoted 6 lines
kernel/bpf/inode.c +0
-0@@ -543,7 +543,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags)return PTR_ERR (raw);For both patches, shall we do the check before
bpf_obj_do_get(), which is a few lines above?
Map does use f_flags, so we need to let them through. Or did you mean to do a (type != BPF_TYPE_MAP && f_flags != O_RDWR) check?
Either way is fine with me, so:
Quoted 14 lines
Thanks,
SongQuoted 10 lines
kernel/bpf/inode.c +1
-2if (type ==BPF_TYPE_PROG ) - ret =bpf_prog_new_fd (raw); + ret = (f_flags !=O_RDWR ) ? -EINVAL :bpf_prog_new_fd (raw);else if (type ==BPF_TYPE_MAP ) ret =bpf_map_new_fd (raw, f_flags);else if (type ==BPF_TYPE_LINK ) --2.27.0
Re: [PATCH bpf v2 2/2] bpf: program: refuse non-O_RDWR flags in BPF_OBJ_GET
In reply to Song LiuQuoted 12 lines · Song Liu
Quoted 10 lines · Lorenz Bauer
As for
bpf_link, refuse creating a non-O_RDWR fd. Since program fds currently don't allow modifications this is a precaution, not a straight up bug fix.Signed-off-by Lorenz Bauer <[email protected]>--- kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Quoted 9 lines
kernel/bpf/inode.c int bpf_obj_get_user(const char __user *pathname, int flags) · line 543
Quoted 6 lines
kernel/bpf/inode.c +0
-0@@ -543,7 +543,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags)return PTR_ERR (raw);For both patches, shall we do the check before
bpf_obj_do_get(), which is a few lines above?
type is filled in by bpf_obj_do_get, so we can't avoid calling it. As Andrii mentions we need to allow flags for map.
Quoted 14 lines
Thanks,
SongQuoted 10 lines
kernel/bpf/inode.c +1
-2if (type ==BPF_TYPE_PROG ) - ret =bpf_prog_new_fd (raw); + ret = (f_flags !=O_RDWR ) ? -EINVAL :bpf_prog_new_fd (raw);else if (type ==BPF_TYPE_MAP ) ret =bpf_map_new_fd (raw, f_flags);else if (type ==BPF_TYPE_LINK ) --2.27.0
Signature · 4 lines
Lorenz Bauer | Systems Engineer 6th Floor, County Hall/The Riverside Building, SE1 7PB, UK www.cloudflare.com
Quoted 7 lines · Lorenz Bauer
Invoking
BPF_OBJ_GETon a pinnedbpf_linkchecks the path access permissions based onfile_flags, but the returned fd ignores flags. This means that any user can acquire a "read-write" fd for a pinned link with mode 0664 by invokingBPF_OBJ_GETwithBPF_F_RDONLYinfile_flags. The fd can be used to invokeBPF_LINK_DETACH, etc.
Quoted 8 lines
Fix this by refusing non-O_RDWR flags in
BPF_OBJ_GET. This works becauseOBJ_GETby default returns a read write mapping and libbpf doesn't expose a way to override this behaviour for programs and links.Fixes 70ed506c3bbc ("bpf: Introduce pinnable bpf_link abstraction")Signed-off-by Lorenz Bauer <[email protected]>---
LGTM.
Quoted 19 lines
kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)kernel/bpf/inode.c +1
-2@@ -547,7 +547,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags)else if (type ==BPF_TYPE_MAP ) ret =bpf_map_new_fd (raw, f_flags);else if (type ==BPF_TYPE_LINK ) - ret =bpf_link_new_fd (raw); + ret = (f_flags !=O_RDWR ) ? -EINVAL :bpf_link_new_fd (raw);else return -ENOENT ; --2.27.0
Quoted 11 lines · Lorenz Bauer
Invoking
BPF_OBJ_GETon a pinnedbpf_linkchecks the path access permissions based onfile_flags, but the returned fd ignores flags. This means that any user can acquire a "read-write" fd for a pinned link with mode 0664 by invokingBPF_OBJ_GETwithBPF_F_RDONLYinfile_flags. The fd can be used to invokeBPF_LINK_DETACH, etc.Fix this by refusing non-O_RDWR flags in
BPF_OBJ_GET. This works becauseOBJ_GETby default returns a read write mapping and libbpf doesn't expose a way to override this behaviour for programs and links.
Hi Alexei and Daniel,
I think these two patches might have fallen through the cracks, could you take a look? I'm not sure what the etiquette is around bumping a set, so please let me know if you'd prefer me to send the patches with acks included or something like that.
Best
Signature · 4 lines
Lorenz Bauer | Systems Engineer 6th Floor, County Hall/The Riverside Building, SE1 7PB, UK www.cloudflare.com
Quoted 14 lines · Lorenz Bauer
Quoted 11 lines · Lorenz Bauer
Invoking
BPF_OBJ_GETon a pinnedbpf_linkchecks the path access permissions based onfile_flags, but the returned fd ignores flags. This means that any user can acquire a "read-write" fd for a pinned link with mode 0664 by invokingBPF_OBJ_GETwithBPF_F_RDONLYinfile_flags. The fd can be used to invokeBPF_LINK_DETACH, etc.Fix this by refusing non-O_RDWR flags in
BPF_OBJ_GET. This works becauseOBJ_GETby default returns a read write mapping and libbpf doesn't expose a way to override this behaviour for programs and links.
Quoted 6 lines
Hi Alexei and Daniel,
I think these two patches might have fallen through the cracks, could you take a look? I'm not sure what the etiquette is around bumping a set, so please let me know if you'd prefer me to send the patches with acks included or something like that.
It is still in patchworks. I didn't have time to think it through. Sorry for delay.
Alexei Starovoitov
AppliedQuoted 14 lines · Lorenz Bauer
Quoted 11 lines · Lorenz Bauer
Invoking
BPF_OBJ_GETon a pinnedbpf_linkchecks the path access permissions based onfile_flags, but the returned fd ignores flags. This means that any user can acquire a "read-write" fd for a pinned link with mode 0664 by invokingBPF_OBJ_GETwithBPF_F_RDONLYinfile_flags. The fd can be used to invokeBPF_LINK_DETACH, etc.Fix this by refusing non-O_RDWR flags in
BPF_OBJ_GET. This works becauseOBJ_GETby default returns a read write mapping and libbpf doesn't expose a way to override this behaviour for programs and links.
Quoted 6 lines
Hi Alexei and Daniel,
I think these two patches might have fallen through the cracks, could you take a look? I'm not sure what the etiquette is around bumping a set, so please let me know if you'd prefer me to send the patches with acks included or something like that.
Applied both. Thanks