Bug Summary

File:.build-ci/../libnvme/src/nvme/ioctl-linux.c
Warning:line 143, column 14
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ioctl-linux.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I libnvme/src/libnvme3.so.3.0.0.p -I libnvme/src -I ../libnvme/src -I ccan -I ../ccan -I . -I .. -I /usr/include/json-c -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -std=gnu99 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-06-24-175442-590-1 -x c ../libnvme/src/nvme/ioctl-linux.c
1// SPDX-License-Identifier: LGPL-2.1-or-later
2/*
3 * This file is part of libnvme.
4 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
5 *
6 * Authors: Keith Busch <keith.busch@wdc.com>
7 * Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
8 */
9#include <errno(*__errno_location ()).h>
10#include <fcntl.h>
11#include <stdint.h>
12#include <stdlib.h>
13#include <string.h>
14#include <unistd.h>
15
16#include <linux1/fs.h>
17
18#include <sys/ioctl.h>
19#include <sys/stat.h>
20
21#include <ccan/build_assert/build_assert.h>
22#include <ccan/endian/endian.h>
23#include <ccan/minmax/minmax.h>
24
25#include <libnvme.h>
26
27#include "private.h"
28#include "compiler-attributes.h"
29
30static int nvme_verify_chr(struct libnvme_transport_handle *hdl)
31{
32 static struct stat nvme_stat;
33 int err = fstat(hdl->fd, &nvme_stat);
34
35 if (err < 0)
36 return -errno(*__errno_location ());
37
38 if (!S_ISCHR(nvme_stat.st_mode)((((nvme_stat.st_mode)) & 0170000) == (0020000)))
39 return -EINVAL22;
40 return 0;
41}
42
43__libnvme_public__attribute__((visibility("default"))) int libnvme_reset_subsystem(
44 struct libnvme_transport_handle *hdl)
45{
46 int ret;
47
48 ret = nvme_verify_chr(hdl);
49 if (ret)
50 return ret;
51
52 ret = ioctl(hdl->fd, LIBNVME_IOCTL_SUBSYS_RESET(((0U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8)) |
(((0x45)) << 0) | ((0) << ((0 +8)+8)))
);
53 if (ret < 0)
54 return -errno(*__errno_location ());
55 return ret;
56}
57
58__libnvme_public__attribute__((visibility("default"))) int libnvme_reset_ctrl(struct libnvme_transport_handle *hdl)
59{
60 int ret;
61
62 ret = nvme_verify_chr(hdl);
63 if (ret)
64 return ret;
65
66 ret = ioctl(hdl->fd, LIBNVME_IOCTL_RESET(((0U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8)) |
(((0x44)) << 0) | ((0) << ((0 +8)+8)))
);
67 if (ret < 0)
68 return -errno(*__errno_location ());
69 return ret;
70}
71
72__libnvme_public__attribute__((visibility("default"))) int libnvme_rescan_ns(struct libnvme_transport_handle *hdl)
73{
74 int ret;
75
76 ret = nvme_verify_chr(hdl);
77 if (ret)
78 return ret;
79
80 ret = ioctl(hdl->fd, LIBNVME_IOCTL_RESCAN(((0U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8)) |
(((0x46)) << 0) | ((0) << ((0 +8)+8)))
);
81 if (ret < 0)
82 return -errno(*__errno_location ());
83 return ret;
84}
85
86__libnvme_public__attribute__((visibility("default"))) int libnvme_get_nsid(
87 struct libnvme_transport_handle *hdl, __u32 *nsid)
88{
89 __u32 tmp;
90
91 errno(*__errno_location ()) = 0;
92 tmp = ioctl(hdl->fd, LIBNVME_IOCTL_ID(((0U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8)) |
(((0x40)) << 0) | ((0) << ((0 +8)+8)))
);
93 if (errno(*__errno_location ()))
94 return -errno(*__errno_location ());
95
96 *nsid = tmp;
97 return 0;
98}
99
100__libnvme_public__attribute__((visibility("default"))) int libnvme_update_block_size(
101 struct libnvme_transport_handle *hdl, int block_size)
102{
103 int ret;
104 libnvme_fd_t fd = libnvme_transport_handle_get_fd(hdl);
105
106 ret = ioctl(fd, BLKBSZSET(((1U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8))
| (((113)) << 0) | ((((sizeof(size_t)))) << ((0 +
8)+8)))
, &block_size);
107 if (ret < 0)
108 return -errno(*__errno_location ());
109
110 ret = ioctl(fd, BLKRRPART(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8))
| (((95)) << 0) | ((0) << ((0 +8)+8)))
);
111 if (ret < 0)
112 return -errno(*__errno_location ());
113
114 return 0;
115}
116
117/*
118 * The 64 bit version is the preferred version to use, but for backwards
119 * compatibility keep a 32 version.
120 */
121static int libnvme_submit_passthru32(struct libnvme_transport_handle *hdl,
122 unsigned long ioctl_cmd, struct libnvme_passthru_cmd *cmd)
123{
124 struct linux_passthru_cmd32 cmd32;
125 void *user_data;
126 int err = 0;
127
128 user_data = hdl->submit_entry(hdl, cmd);
129 if (hdl->ctx->dry_run)
16
Assuming field 'dry_run' is true
17
Taking true branch
130 goto out;
18
Control jumps to line 143
131
132 memcpy(&cmd32, cmd, offsetof(struct linux_passthru_cmd32, result)__builtin_offsetof(struct linux_passthru_cmd32, result));
133 cmd32.result = 0;
134
135 do {
136 err = ioctl(hdl->fd, ioctl_cmd, &cmd32);
137 if (err >= 0)
138 break;
139 err = -errno(*__errno_location ());
140 } while (hdl->decide_retry(hdl, cmd, err));
141
142out:
143 cmd->result = cmd32.result;
19
Assigned value is garbage or undefined
144 hdl->submit_exit(hdl, cmd, err, user_data);
145 return err;
146}
147
148/*
149 * supported since kernel 5.4, see
150 * 65e68edce0db ("nvme: allow 64-bit results in passthru commands")
151 */
152static int libnvme_submit_passthru64(struct libnvme_transport_handle *hdl,
153 unsigned long ioctl_cmd, struct libnvme_passthru_cmd *cmd)
154{
155 void *user_data;
156 int err = 0;
157
158 user_data = hdl->submit_entry(hdl, cmd);
159 if (hdl->ctx->dry_run)
160 goto out;
161
162 do {
163 /*
164 * struct nvme_passtrhu_cmd is identically to struct
165 * linux_passthru_cmd64, thus just pass it in directly.
166 */
167 err = ioctl(hdl->fd, ioctl_cmd, cmd);
168 if (err >= 0)
169 break;
170 err = -errno(*__errno_location ());
171 } while (hdl->decide_retry(hdl, cmd, err));
172
173out:
174 hdl->submit_exit(hdl, cmd, err, user_data);
175 return err;
176}
177
178__libnvme_public__attribute__((visibility("default"))) int libnvme_submit_io_passthru(
179 struct libnvme_transport_handle *hdl,
180 struct libnvme_passthru_cmd *cmd)
181{
182 int err;
183
184 if (!hdl
10.1
'hdl' is non-null
)
185 return -ENODEV19;
186
187 if (!cmd->timeout_ms && hdl->timeout)
11
Assuming field 'timeout_ms' is not equal to 0
188 cmd->timeout_ms = hdl->timeout;
189
190 if (hdl->ioctl_io_state == IOCTL_STATE_IOCTL64)
12
Assuming field 'ioctl_io_state' is not equal to IOCTL_STATE_IOCTL64
191 return libnvme_submit_passthru64(hdl,
192 LIBNVME_IOCTL_IO64_CMD(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x48)) << 0) | ((((sizeof(struct linux_passthru_cmd64
)))) << ((0 +8)+8)))
, cmd);
193
194 if (hdl->ioctl_io_state == IOCTL_STATE_IOCTL32 ||
13
Assuming field 'ioctl_io_state' is equal to IOCTL_STATE_IOCTL32
195 !hdl->ctx->ioctl_probing)
196 goto do_ioctl32;
14
Control jumps to line 207
197
198 err = libnvme_submit_passthru64(hdl, LIBNVME_IOCTL_IO64_CMD(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x48)) << 0) | ((((sizeof(struct linux_passthru_cmd64
)))) << ((0 +8)+8)))
, cmd);
199 if (err >= 0 || err != -ENOTTY25) {
200 hdl->ioctl_io_state = IOCTL_STATE_IOCTL64;
201 return err;
202 }
203
204 hdl->ioctl_io_state = IOCTL_STATE_IOCTL32;
205
206do_ioctl32:
207 return libnvme_submit_passthru32(hdl, LIBNVME_IOCTL_IO_CMD(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x43)) << 0) | ((((sizeof(struct linux_passthru_cmd32
)))) << ((0 +8)+8)))
, cmd)
;
15
Calling 'libnvme_submit_passthru32'
208}
209
210static int submit_admin_passthru(struct libnvme_transport_handle *hdl,
211 struct libnvme_passthru_cmd *cmd)
212{
213 int err;
214
215 if (hdl->ioctl_admin_state == IOCTL_STATE_IOCTL64)
216 return libnvme_submit_passthru64(hdl,
217 LIBNVME_IOCTL_ADMIN64_CMD(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x47)) << 0) | ((((sizeof(struct linux_passthru_cmd64
)))) << ((0 +8)+8)))
, cmd);
218
219 if (hdl->ioctl_admin_state == IOCTL_STATE_IOCTL32 ||
220 !hdl->ctx->ioctl_probing)
221 goto do_ioctl32;
222
223 err = libnvme_submit_passthru64(hdl, LIBNVME_IOCTL_ADMIN64_CMD(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x47)) << 0) | ((((sizeof(struct linux_passthru_cmd64
)))) << ((0 +8)+8)))
, cmd);
224 if (err >= 0 || err != -ENOTTY25) {
225 hdl->ioctl_admin_state = IOCTL_STATE_IOCTL64;
226 return err;
227 }
228
229 hdl->ioctl_admin_state = IOCTL_STATE_IOCTL32;
230
231do_ioctl32:
232 if (cmd->opcode == nvme_admin_fabrics)
233 return -ENOTSUP95;
234
235 return libnvme_submit_passthru32(hdl, LIBNVME_IOCTL_ADMIN_CMD(((2U|1U) << (((0 +8)+8)+14)) | ((('N')) << (0 +8
)) | (((0x41)) << 0) | ((((sizeof(struct linux_passthru_cmd32
)))) << ((0 +8)+8)))
, cmd);
236}
237
238__libnvme_public__attribute__((visibility("default"))) int libnvme_submit_admin_passthru(
239 struct libnvme_transport_handle *hdl,
240 struct libnvme_passthru_cmd *cmd)
241{
242 if (!hdl)
243 return -ENODEV19;
244
245 if (!cmd->timeout_ms && hdl->timeout)
246 cmd->timeout_ms = hdl->timeout;
247
248 switch (hdl->type) {
249 case LIBNVME_TRANSPORT_HANDLE_TYPE_DIRECT:
250 return submit_admin_passthru(hdl, cmd);
251 case LIBNVME_TRANSPORT_HANDLE_TYPE_MI:
252 return libnvme_mi_admin_admin_passthru(hdl, cmd);
253 default:
254 break;
255 }
256
257 return -ENOTSUP95;
258}
259
260__libnvme_public__attribute__((visibility("default"))) int libnvme_exec_admin_passthru(
261 struct libnvme_transport_handle *hdl,
262 struct libnvme_passthru_cmd *cmd)
263{
264 struct libnvme_passthru_completion completion;
265 int err;
266
267 if (!hdl)
268 return -ENODEV19;
269
270 if (hdl->uring_state == LIBNVME_IO_URING_STATE_NOT_AVAILABLE)
271 goto no_uring;
272
273 err = libnvme_submit_admin_passthru_async(hdl, cmd, NULL((void*)0));
274 if (err) {
275 if (err == -ENOTSUP95)
276 goto no_uring;
277
278 return err;
279 }
280
281 err = libnvme_reap_passthru_async(hdl, &completion);
282 if (err)
283 return err;
284
285 return completion.status;
286
287no_uring:
288 return libnvme_submit_admin_passthru(hdl, cmd);
289}
290
291__libnvme_public__attribute__((visibility("default"))) int libnvme_exec_io_passthru(
292 struct libnvme_transport_handle *hdl,
293 struct libnvme_passthru_cmd *cmd)
294{
295 struct libnvme_passthru_completion completion;
296 int err;
297
298 if (!hdl)
1
Assuming 'hdl' is non-null
2
Taking false branch
299 return -ENODEV19;
300
301 if (hdl->uring_state == LIBNVME_IO_URING_STATE_NOT_AVAILABLE)
3
Assuming field 'uring_state' is not equal to LIBNVME_IO_URING_STATE_NOT_AVAILABLE
4
Taking false branch
302 goto no_uring;
303
304 err = libnvme_submit_io_passthru_async(hdl, cmd, NULL((void*)0));
305 if (err) {
5
Assuming 'err' is not equal to 0
6
Taking true branch
306 if (err == -ENOTSUP95)
7
Assuming the condition is true
8
Taking true branch
307 goto no_uring;
9
Control jumps to line 319
308
309 return err;
310 }
311
312 err = libnvme_reap_passthru_async(hdl, &completion);
313 if (err)
314 return err;
315
316 return completion.status;
317
318no_uring:
319 return libnvme_submit_io_passthru(hdl, cmd);
10
Calling 'libnvme_submit_io_passthru'
320}