1 /*
2 * Copyright (c) 2012 The Chromium OS Authors.
3 * Copyright (c) 2012-2021 The strace developers.
4 * Written by Mike Frysinger <vapier@gentoo.org>.
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8
9 #include "defs.h"
10
11 #include DEF_MPERS_TYPE(struct_loop_info)
12
13 #include <linux/loop.h>
14
15 typedef struct loop_info struct_loop_info;
16
17 #include MPERS_DEFS
18
19 #include "xlat/loop_flags_options.h"
20 #include "xlat/loop_crypt_type_options.h"
21
22 static void
23 decode_loop_info(struct tcb *const tcp, const kernel_ulong_t addr)
24 {
25 struct_loop_info info;
26
27 if (umove_or_printaddr(tcp, addr, &info))
28 return;
29
30 tprint_struct_begin();
31 PRINT_FIELD_D(info, lo_number);
32
33 if (!abbrev(tcp)) {
34 tprint_struct_next();
35 PRINT_FIELD_DEV(info, lo_device);
36 tprint_struct_next();
37 PRINT_FIELD_U(info, lo_inode);
38 tprint_struct_next();
39 PRINT_FIELD_DEV(info, lo_rdevice);
40 }
41
42 tprint_struct_next();
43 PRINT_FIELD_X(info, lo_offset);
44
45 if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
46 tprint_struct_next();
47 PRINT_FIELD_XVAL(info, lo_encrypt_type,
48 loop_crypt_type_options, "LO_CRYPT_???");
49 /*
50 * It is converted to unsigned before use in the kernel,
51 * see loop_info64_from_old in drivers/block/loop.c
52 */
53 tprint_struct_next();
54 PRINT_FIELD_U(info, lo_encrypt_key_size);
55 }
56
57 tprint_struct_next();
58 PRINT_FIELD_FLAGS(info, lo_flags, loop_flags_options, "LO_FLAGS_???");
59
60 tprint_struct_next();
61 PRINT_FIELD_CSTRING(info, lo_name);
62
63 if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
64 const unsigned int lo_encrypt_key_size =
65 MIN((unsigned) info.lo_encrypt_key_size, LO_KEY_SIZE);
66 tprint_struct_next();
67 PRINT_FIELD_STRING(info, lo_encrypt_key,
68 lo_encrypt_key_size, 0);
69 }
70
71 if (!abbrev(tcp)) {
72 tprint_struct_next();
73 PRINT_FIELD_X_ARRAY(info, lo_init);
74 tprint_struct_next();
75 PRINT_FIELD_X_ARRAY(info, reserved);
76 } else {
77 tprint_struct_next();
78 tprint_more_data_follows();
79 }
80
81 tprint_struct_end();
82 }
83
84 static void
85 print_loop_info64(struct tcb *const tcp, const struct loop_info64 *const info64)
86 {
87 if (!abbrev(tcp)) {
88 tprint_struct_begin();
89 PRINT_FIELD_DEV(*info64, lo_device);
90 tprint_struct_next();
91 PRINT_FIELD_U(*info64, lo_inode);
92 tprint_struct_next();
93 PRINT_FIELD_DEV(*info64, lo_rdevice);
94 tprint_struct_next();
95 PRINT_FIELD_X(*info64, lo_offset);
96 tprint_struct_next();
97 PRINT_FIELD_U(*info64, lo_sizelimit);
98 tprint_struct_next();
99 PRINT_FIELD_U(*info64, lo_number);
100 } else {
101 tprint_struct_begin();
102 PRINT_FIELD_X(*info64, lo_offset);
103 tprint_struct_next();
104 PRINT_FIELD_U(*info64, lo_number);
105 }
106
107 if (!abbrev(tcp) || info64->lo_encrypt_type != LO_CRYPT_NONE) {
108 tprint_struct_next();
109 PRINT_FIELD_XVAL(*info64, lo_encrypt_type,
110 loop_crypt_type_options, "LO_CRYPT_???");
111 tprint_struct_next();
112 PRINT_FIELD_U(*info64, lo_encrypt_key_size);
113 }
114
115 tprint_struct_next();
116 PRINT_FIELD_FLAGS(*info64, lo_flags, loop_flags_options, "LO_FLAGS_???");
117
118 tprint_struct_next();
119 PRINT_FIELD_CSTRING(*info64, lo_file_name);
120
121 if (!abbrev(tcp) || info64->lo_encrypt_type != LO_CRYPT_NONE) {
122 tprint_struct_next();
123 PRINT_FIELD_CSTRING(*info64, lo_crypt_name);
124 const unsigned int lo_encrypt_key_size =
125 MIN((unsigned) info64->lo_encrypt_key_size, LO_KEY_SIZE);
126 tprint_struct_next();
127 PRINT_FIELD_STRING(*info64, lo_encrypt_key,
128 lo_encrypt_key_size, 0);
129 }
130
131 if (!abbrev(tcp)) {
132 tprint_struct_next();
133 PRINT_FIELD_X_ARRAY(*info64, lo_init);
134 } else {
135 tprint_struct_next();
136 tprint_more_data_follows();
137 }
138
139 tprint_struct_end();
140 }
141
142 static void
143 decode_loop_info64(struct tcb *const tcp, const kernel_ulong_t addr)
144 {
145 struct loop_info64 info64;
146
147 if (!umove_or_printaddr(tcp, addr, &info64))
148 print_loop_info64(tcp, &info64);
149 }
150
151 static void
152 decode_loop_config(struct tcb *const tcp, const kernel_ulong_t addr)
153 {
154 struct loop_config config;
155
156 if (umove_or_printaddr(tcp, addr, &config))
157 return;
158
159 tprint_struct_begin();
160 PRINT_FIELD_FD(config, fd, tcp);
161
162 tprint_struct_next();
163 PRINT_FIELD_U(config, block_size);
164
165 tprint_struct_next();
166 PRINT_FIELD_OBJ_TCB_PTR(config, info, tcp, print_loop_info64);
167
168 if (!IS_ARRAY_ZERO(config.__reserved)) {
169 tprint_struct_next();
170 PRINT_FIELD_X_ARRAY(config, __reserved);
171 }
172
173 tprint_struct_end();
174 }
175
176 MPERS_PRINTER_DECL(int, loop_ioctl,
177 struct tcb *tcp, const unsigned int code,
178 const kernel_ulong_t arg)
179 {
180 switch (code) {
181 case LOOP_GET_STATUS:
182 if (entering(tcp))
183 return 0;
184 ATTRIBUTE_FALLTHROUGH;
185 case LOOP_SET_STATUS:
186 tprint_arg_next();
187 decode_loop_info(tcp, arg);
188 break;
189
190 case LOOP_GET_STATUS64:
191 if (entering(tcp))
192 return 0;
193 ATTRIBUTE_FALLTHROUGH;
194 case LOOP_SET_STATUS64:
195 tprint_arg_next();
196 decode_loop_info64(tcp, arg);
197 break;
198
199 case LOOP_CONFIGURE:
200 tprint_arg_next();
201 decode_loop_config(tcp, arg);
202 break;
203
204 case LOOP_CLR_FD:
205 case LOOP_SET_CAPACITY:
206 /* newer loop-control stuff */
207 case LOOP_CTL_GET_FREE:
208 /* Takes no arguments */
209 break;
210
211 case LOOP_SET_FD:
212 case LOOP_CHANGE_FD:
213 tprint_arg_next();
214 printfd(tcp, arg);
215 break;
216
217 /* newer loop-control stuff */
218 case LOOP_CTL_ADD:
219 case LOOP_CTL_REMOVE:
220 tprint_arg_next();
221 PRINT_VAL_D((int) arg);
222 break;
223
224 case LOOP_SET_DIRECT_IO:
225 case LOOP_SET_BLOCK_SIZE:
226 tprint_arg_next();
227 PRINT_VAL_U(arg);
228 break;
229
230 default:
231 return RVAL_DECODED;
232 }
233
234 return RVAL_IOCTL_DECODED;
235 }