xref: /linux/tools/testing/selftests/bpf/progs/file_reader_fail.c (revision 84f7a49e76ec8e0a1e18f3758e89800f8cf8cfc6)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
3 
4 #include <vmlinux.h>
5 #include <string.h>
6 #include <stdbool.h>
7 #include <bpf/bpf_tracing.h>
8 #include "bpf_misc.h"
9 
10 char _license[] SEC("license") = "GPL";
11 
12 int err;
13 void *user_ptr;
14 
15 SEC("lsm/file_open")
16 __failure
17 __msg("Unreleased reference id=")
18 int on_nanosleep_unreleased_ref(void *ctx)
19 {
20 	struct task_struct *task = bpf_get_current_task_btf();
21 	struct file *file = bpf_get_task_exe_file(task);
22 	struct bpf_dynptr dynptr;
23 
24 	if (!file)
25 		return 0;
26 
27 	err = bpf_dynptr_from_file(file, 0, &dynptr);
28 	return err ? 1 : 0;
29 }
30 
31 SEC("xdp")
32 __failure
33 __msg("Expected a dynptr of type file as R1")
34 int xdp_wrong_dynptr_type(struct xdp_md *xdp)
35 {
36 	struct bpf_dynptr dynptr;
37 
38 	bpf_dynptr_from_xdp(xdp, 0, &dynptr);
39 	bpf_dynptr_file_discard(&dynptr);
40 	return 0;
41 }
42 
43 SEC("xdp")
44 __failure
45 __msg("Expected an initialized dynptr as R1")
46 int xdp_no_dynptr_type(struct xdp_md *xdp)
47 {
48 	struct bpf_dynptr dynptr;
49 
50 	bpf_dynptr_file_discard(&dynptr);
51 	return 0;
52 }
53 
54 SEC("lsm/file_open")
55 __failure
56 __msg("Leaking reference id={{[0-9]+}} alloc_insn={{[0-9]+}}. Release it first.")
57 int use_file_dynptr_after_put_file(void *ctx)
58 {
59 	struct task_struct *task = bpf_get_current_task_btf();
60 	struct file *file = bpf_get_task_exe_file(task);
61 	struct bpf_dynptr dynptr;
62 	char buf[64];
63 
64 	if (!file)
65 		return 0;
66 
67 	if (bpf_dynptr_from_file(file, 0, &dynptr))
68 		goto out;
69 
70 	/* this should fail - file dynptr should be discarded first to prevent resource leak */
71 	bpf_put_file(file);
72 
73 	bpf_dynptr_read(buf, sizeof(buf), &dynptr, 0, 0);
74 	return 0;
75 
76 out:
77 	bpf_dynptr_file_discard(&dynptr);
78 	bpf_put_file(file);
79 	return 0;
80 }
81 
82 SEC("lsm/file_open")
83 __failure
84 __msg("Leaking reference id={{[0-9]+}} alloc_insn={{[0-9]+}}. Release it first.")
85 int use_file_dynptr_slice_after_put_file(void *ctx)
86 {
87 	struct task_struct *task = bpf_get_current_task_btf();
88 	struct file *file = bpf_get_task_exe_file(task);
89 	struct bpf_dynptr dynptr;
90 	char *data;
91 
92 	if (!file)
93 		return 0;
94 
95 	if (bpf_dynptr_from_file(file, 0, &dynptr))
96 		goto out;
97 
98 	data = bpf_dynptr_data(&dynptr, 0, 1);
99 	if (!data)
100 		goto out;
101 
102 	/* this should fail - file dynptr should be discarded first to prevent resource leak */
103 	bpf_put_file(file);
104 
105 	*data = 'x';
106 	return 0;
107 
108 out:
109 	bpf_dynptr_file_discard(&dynptr);
110 	bpf_put_file(file);
111 	return 0;
112 }
113