• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009, 2010 Jeff Mahoney <jeffm@suse.com>
3  * Copyright (c) 2011-2016 Dmitry V. Levin <ldv@altlinux.org>
4  * Copyright (c) 2011-2018 The strace developers.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "defs.h"
31 
32 #include DEF_MPERS_TYPE(struct_blk_user_trace_setup)
33 #include DEF_MPERS_TYPE(struct_blkpg_ioctl_arg)
34 #include DEF_MPERS_TYPE(struct_blkpg_partition)
35 
36 #include <linux/ioctl.h>
37 #include <linux/fs.h>
38 
39 typedef struct {
40 	int op;
41 	int flags;
42 	int datalen;
43 	void *data;
44 } struct_blkpg_ioctl_arg;
45 
46 #define BLKPG_DEVNAMELTH	64
47 #define BLKPG_VOLNAMELTH	64
48 typedef struct {
49 	int64_t start;			/* starting offset in bytes */
50 	int64_t length;			/* length in bytes */
51 	int pno;			/* partition number */
52 	char devname[BLKPG_DEVNAMELTH];	/* partition name, like sda5 or c0d1p2,
53 					   to be used in kernel messages */
54 	char volname[BLKPG_VOLNAMELTH];	/* volume label */
55 } struct_blkpg_partition;
56 
57 #define BLKTRACE_BDEV_SIZE      32
58 typedef struct blk_user_trace_setup {
59 	char name[BLKTRACE_BDEV_SIZE];	/* output */
60 	uint16_t act_mask;		/* input */
61 	uint32_t buf_size;		/* input */
62 	uint32_t buf_nr;		/* input */
63 	uint64_t start_lba;
64 	uint64_t end_lba;
65 	uint32_t pid;
66 } struct_blk_user_trace_setup;
67 
68 /* Provide fall-back definitions for BLK* ioctls */
69 #define XLAT_MACROS_ONLY
70 # include "xlat/block_ioctl_cmds.h"
71 #undef XLAT_MACROS_ONLY
72 
73 #include MPERS_DEFS
74 
75 #include "print_fields.h"
76 
77 #include "xlat/blkpg_ops.h"
78 
79 static void
print_blkpg_req(struct tcb * tcp,const struct_blkpg_ioctl_arg * blkpg)80 print_blkpg_req(struct tcb *tcp, const struct_blkpg_ioctl_arg *blkpg)
81 {
82 	struct_blkpg_partition p;
83 
84 	PRINT_FIELD_XVAL("{", *blkpg, op, blkpg_ops, "BLKPG_???");
85 	PRINT_FIELD_D(", ", *blkpg, flags);
86 	PRINT_FIELD_D(", ", *blkpg, datalen);
87 
88 	tprints(", data=");
89 	if (!umove_or_printaddr(tcp, ptr_to_kulong(blkpg->data), &p)) {
90 		PRINT_FIELD_D("{", p, start);
91 		PRINT_FIELD_D(", ", p, length);
92 		PRINT_FIELD_D(", ", p, pno);
93 		PRINT_FIELD_CSTRING(", ", p, devname);
94 		PRINT_FIELD_CSTRING(", ", p, volname);
95 		tprints("}");
96 	}
97 	tprints("}");
98 }
99 
MPERS_PRINTER_DECL(int,block_ioctl,struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)100 MPERS_PRINTER_DECL(int, block_ioctl, struct tcb *const tcp,
101 		   const unsigned int code, const kernel_ulong_t arg)
102 {
103 	switch (code) {
104 	/* take arg as a value, not as a pointer */
105 	case BLKRASET:
106 	case BLKFRASET:
107 		tprintf(", %" PRI_klu, arg);
108 		break;
109 
110 	/* return an unsigned short */
111 	case BLKSECTGET:
112 	case BLKROTATIONAL:
113 		if (entering(tcp))
114 			return 0;
115 		tprints(", ");
116 		printnum_short(tcp, arg, "%hu");
117 		break;
118 
119 	/* return a signed int */
120 	case BLKROGET:
121 	case BLKBSZGET:
122 	case BLKSSZGET:
123 	case BLKALIGNOFF:
124 		if (entering(tcp))
125 			return 0;
126 		ATTRIBUTE_FALLTHROUGH;
127 	/* take a signed int */
128 	case BLKROSET:
129 	case BLKBSZSET:
130 		tprints(", ");
131 		printnum_int(tcp, arg, "%d");
132 		break;
133 
134 	/* return an unsigned int */
135 	case BLKPBSZGET:
136 	case BLKIOMIN:
137 	case BLKIOOPT:
138 	case BLKDISCARDZEROES:
139 		if (entering(tcp))
140 			return 0;
141 		tprints(", ");
142 		printnum_int(tcp, arg, "%u");
143 		break;
144 
145 	/* return a signed long */
146 	case BLKRAGET:
147 	case BLKFRAGET:
148 		if (entering(tcp))
149 			return 0;
150 		tprints(", ");
151 		printnum_slong(tcp, arg);
152 		break;
153 
154 	/* returns an unsigned long */
155 	case BLKGETSIZE:
156 		if (entering(tcp))
157 			return 0;
158 		tprints(", ");
159 		printnum_ulong(tcp, arg);
160 		break;
161 
162 	/* returns an uint64_t */
163 	case BLKGETSIZE64:
164 		if (entering(tcp))
165 			return 0;
166 		tprints(", ");
167 		printnum_int64(tcp, arg, "%" PRIu64);
168 		break;
169 
170 	/* takes a pair of uint64_t */
171 	case BLKDISCARD:
172 	case BLKSECDISCARD:
173 	case BLKZEROOUT:
174 		tprints(", ");
175 		printpair_int64(tcp, arg, "%" PRIu64);
176 		break;
177 
178 	/* More complex types */
179 	case BLKPG: {
180 		struct_blkpg_ioctl_arg blkpg;
181 
182 		tprints(", ");
183 		if (!umove_or_printaddr(tcp, arg, &blkpg))
184 			print_blkpg_req(tcp, &blkpg);
185 		break;
186 	}
187 
188 	case BLKTRACESETUP:
189 		if (entering(tcp)) {
190 			struct_blk_user_trace_setup buts;
191 
192 			tprints(", ");
193 			if (umove_or_printaddr(tcp, arg, &buts))
194 				break;
195 			PRINT_FIELD_U("{", buts, act_mask);
196 			PRINT_FIELD_U(", ", buts, buf_size);
197 			PRINT_FIELD_U(", ", buts, buf_nr);
198 			PRINT_FIELD_U(", ", buts, start_lba);
199 			PRINT_FIELD_U(", ", buts, end_lba);
200 			PRINT_FIELD_U(", ", buts, pid);
201 			return 0;
202 		} else {
203 			struct_blk_user_trace_setup buts;
204 
205 			if (!syserror(tcp) && !umove(tcp, arg, &buts))
206 				PRINT_FIELD_CSTRING(", ", buts, name);
207 			tprints("}");
208 			break;
209 		}
210 
211 	/* No arguments */
212 	case BLKRRPART:
213 	case BLKFLSBUF:
214 	case BLKTRACESTART:
215 	case BLKTRACESTOP:
216 	case BLKTRACETEARDOWN:
217 		break;
218 	default:
219 		return RVAL_DECODED;
220 	}
221 
222 	return RVAL_IOCTL_DECODED;
223 }
224