1 /*
2 * Copyright (c) 2015 Dmitry V. Levin <ldv@strace.io>
3 * Copyright (c) 2015-2023 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8
9 #include "defs.h"
10 #include <linux/fcntl.h>
11 #include "xlat/name_to_handle_at_flags.h"
12
13 #ifndef MAX_HANDLE_SZ
14 # define MAX_HANDLE_SZ 128
15 #endif
16
17 typedef struct {
18 unsigned int handle_bytes;
19 int handle_type;
20 } file_handle_header;
21
22 static void
23 print_f_handle(struct tcb *tcp, kernel_ulong_t addr, unsigned int handle_bytes)
24 {
25 unsigned int len = MIN(handle_bytes, MAX_HANDLE_SZ);
26 char f_handle[MAX_HANDLE_SZ];
27 addr += sizeof(file_handle_header);
28 if (addr > sizeof(file_handle_header) &&
29 !umoven(tcp, addr, len, f_handle)) {
30 print_quoted_string(f_handle, len, QUOTE_FORCE_HEX);
31 if (handle_bytes > len)
32 tprint_more_data_follows();
33 } else {
34 tprint_unavailable();
35 }
36 }
37
38 SYS_FUNC(name_to_handle_at)
39 {
40 file_handle_header h;
41 const kernel_ulong_t addr = tcp->u_arg[2];
42
43 if (entering(tcp)) {
44 /* dirfd */
45 print_dirfd(tcp, tcp->u_arg[0]);
46 tprint_arg_next();
47
48 /* pathname */
49 printpath(tcp, tcp->u_arg[1]);
50 tprint_arg_next();
51
52 /* handle */
53 if (umove_or_printaddr(tcp, addr, &h)) {
54 tprint_arg_next();
55
56 /* mount_id */
57 printaddr(tcp->u_arg[3]);
58 tprint_arg_next();
59
60 /* flags */
61 printflags(name_to_handle_at_flags, tcp->u_arg[4],
62 "AT_???");
63
64 return RVAL_DECODED;
65 }
66
67 tprint_struct_begin();
68 PRINT_FIELD_U(h, handle_bytes);
69
70 set_tcb_priv_ulong(tcp, h.handle_bytes);
71
72 return 0;
73 } else {
74 if ((!syserror(tcp) || EOVERFLOW == tcp->u_error)
75 && !umove(tcp, addr, &h)) {
76
77 if (h.handle_bytes != get_tcb_priv_ulong(tcp)) {
78 tprint_value_changed();
79 PRINT_VAL_U(h.handle_bytes);
80 }
81 if (!syserror(tcp)) {
82 tprint_struct_next();
83 PRINT_FIELD_D(h, handle_type);
84 tprint_struct_next();
85 tprints_field_name("f_handle");
86 print_f_handle(tcp, addr, h.handle_bytes);
87 }
88 }
89 tprint_struct_end();
90 tprint_arg_next();
91
92 /* mount_id */
93 printnum_int(tcp, tcp->u_arg[3], "%d");
94 tprint_arg_next();
95
96 /* flags */
97 printflags(name_to_handle_at_flags, tcp->u_arg[4], "AT_???");
98 }
99 return 0;
100 }
101
102 SYS_FUNC(open_by_handle_at)
103 {
104 file_handle_header h;
105 const kernel_ulong_t addr = tcp->u_arg[1];
106
107 /* mount_fd */
108 printfd(tcp, tcp->u_arg[0]);
109 tprint_arg_next();
110
111 /* handle */
112 if (!umove_or_printaddr(tcp, addr, &h)) {
113 tprint_struct_begin();
114 PRINT_FIELD_U(h, handle_bytes);
115 tprint_struct_next();
116 PRINT_FIELD_D(h, handle_type);
117 tprint_struct_next();
118 tprints_field_name("f_handle");
119 print_f_handle(tcp, addr, h.handle_bytes);
120 tprint_struct_end();
121 }
122 tprint_arg_next();
123
124 /* flags */
125 tprint_open_modes(tcp->u_arg[2]);
126
127 return RVAL_DECODED | RVAL_FD;
128 }