diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | defs.h | 1 | ||||
-rw-r--r-- | ioctl.c | 2 | ||||
-rw-r--r-- | nbd_ioctl.c | 73 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/gen_tests.in | 1 | ||||
-rw-r--r-- | tests/ioctl_nbd.c | 112 | ||||
-rwxr-xr-x | tests/pure_executables.list | 1 | ||||
-rw-r--r-- | xlat/nbd_ioctl_cmds.in | 11 | ||||
-rw-r--r-- | xlat/nbd_ioctl_flags.in | 29 |
10 files changed, 232 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 9e5eef276..913d26a9e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -204,6 +204,7 @@ strace_SOURCES = \ msghdr.h \ mtd.c \ native_defs.h \ + nbd_ioctl.c \ negated_errno.h \ net.c \ netlink.c \ @@ -970,6 +970,7 @@ DECL_IOCTL(file); DECL_IOCTL(fs_x); DECL_IOCTL(inotify); DECL_IOCTL(kvm); +DECL_IOCTL(nbd); DECL_IOCTL(nsfs); DECL_IOCTL(ptp); DECL_IOCTL(scsi); @@ -327,6 +327,8 @@ ioctl_decode(struct tcb *tcp) #endif case 'I': return inotify_ioctl(tcp, code, arg); + case 0xab: + return nbd_ioctl(tcp, code, arg); default: break; } diff --git a/nbd_ioctl.c b/nbd_ioctl.c new file mode 100644 index 000000000..0ceec3e8a --- /dev/null +++ b/nbd_ioctl.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 The strace developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "defs.h" +#include "print_fields.h" +#include <linux/ioctl.h> +#include <linux/types.h> +#include <linux/nbd.h> + +#define XLAT_MACROS_ONLY +# include "xlat/nbd_ioctl_cmds.h" +#undef XLAT_MACROS_ONLY + +#include "xlat/nbd_ioctl_flags.h" + +int +nbd_ioctl(struct tcb *const tcp, const unsigned int code, + const kernel_ulong_t arg) +{ + switch (code) { + case NBD_DISCONNECT: + case NBD_CLEAR_SOCK: + case NBD_DO_IT: + case NBD_CLEAR_QUE: + case NBD_PRINT_DEBUG: + return RVAL_IOCTL_DECODED; + + case NBD_SET_SOCK: + tprints(", "); + printfd(tcp, arg); + return RVAL_IOCTL_DECODED; + + case NBD_SET_BLKSIZE: + case NBD_SET_SIZE: + case NBD_SET_SIZE_BLOCKS: + case NBD_SET_TIMEOUT: + tprints(", "); + tprintf("%" PRI_klu, arg); + return RVAL_IOCTL_DECODED; + + case NBD_SET_FLAGS: + tprints(", "); + printflags(nbd_ioctl_flags, arg, "NBD_IOC_FLAG_???"); + return RVAL_IOCTL_DECODED; + + default: + return RVAL_DECODED; + } +} diff --git a/tests/.gitignore b/tests/.gitignore index a7f201ee2..577a1316d 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -153,6 +153,7 @@ ioctl_loop ioctl_loop-nv ioctl_loop-v ioctl_mtd +ioctl_nbd ioctl_nsfs ioctl_perf ioctl_perf-success diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 16638970d..cd63788d8 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -146,6 +146,7 @@ ioctl_loop +ioctl.test ioctl_loop-nv +ioctl.test -a22 -e verbose=none ioctl_loop-v +ioctl.test -v ioctl_mtd +ioctl.test +ioctl_nbd +ioctl.test -y ioctl_nsfs +ioctl.test -esignal=none ioctl_perf +ioctl.test ioctl_ptp +ioctl.test diff --git a/tests/ioctl_nbd.c b/tests/ioctl_nbd.c new file mode 100644 index 000000000..7daeec48f --- /dev/null +++ b/tests/ioctl_nbd.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018 The strace developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" + +#include <fcntl.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <linux/types.h> +#include <linux/nbd.h> + +#define XLAT_MACROS_ONLY +# include "xlat/nbd_ioctl_cmds.h" +# include "xlat/nbd_ioctl_flags.h" +#undef XLAT_MACROS_ONLY + +#define RVAL_EBADF " = -1 EBADF (%m)\n" + +int +main(void) +{ + static const unsigned long ubeef = (unsigned long) 0xcafef00ddeadbeefULL; + static const char null_path[] = "/dev/null"; + + int fd = open(null_path, O_RDONLY); + if (fd < 0) + perror_msg_and_fail("open(\"%s\")", null_path); + + skip_if_unavailable("/proc/self/fd/"); + + ioctl(-1, NBD_DISCONNECT, NULL); + printf("ioctl(-1, NBD_DISCONNECT)" RVAL_EBADF); + ioctl(-1, NBD_CLEAR_SOCK, NULL); + printf("ioctl(-1, NBD_CLEAR_SOCK)" RVAL_EBADF); + ioctl(-1, NBD_DO_IT, NULL); + printf("ioctl(-1, NBD_DO_IT)" RVAL_EBADF); + ioctl(-1, NBD_CLEAR_QUE, NULL); + printf("ioctl(-1, NBD_CLEAR_QUE)" RVAL_EBADF); + ioctl(-1, NBD_PRINT_DEBUG, NULL); + printf("ioctl(-1, NBD_PRINT_DEBUG)" RVAL_EBADF); + ioctl(-1, NBD_SET_SOCK, fd); + printf("ioctl(-1, NBD_SET_SOCK, %d</dev/null>)" RVAL_EBADF, fd); + + ioctl(-1, NBD_SET_BLKSIZE, ubeef); + printf("ioctl(-1, NBD_SET_BLKSIZE, %lu)" RVAL_EBADF, ubeef); + ioctl(-1, NBD_SET_SIZE, ubeef); + printf("ioctl(-1, NBD_SET_SIZE, %lu)" RVAL_EBADF, ubeef); + ioctl(-1, NBD_SET_SIZE_BLOCKS, ubeef); + printf("ioctl(-1, NBD_SET_SIZE_BLOCKS, %lu)" RVAL_EBADF, ubeef); + + ioctl(-1, NBD_SET_TIMEOUT, ubeef); + printf("ioctl(-1, NBD_SET_TIMEOUT, %lu)" RVAL_EBADF, ubeef); + + ioctl(-1, NBD_SET_FLAGS, 0); + printf("ioctl(-1, NBD_SET_FLAGS, 0)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_HAS_FLAGS); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_HAS_FLAGS)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_READ_ONLY); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_READ_ONLY)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_FLUSH); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_FLUSH)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_FUA); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_FUA)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_WRITE_ZEROES); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_WRITE_ZEROES)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_DF); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_DF)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_CAN_MULTI_CONN); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_CAN_MULTI_CONN)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_RESIZE); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_RESIZE)" RVAL_EBADF); + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_CACHE); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_SEND_CACHE)" RVAL_EBADF); + + ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_HAS_FLAGS|NBD_FLAG_READ_ONLY| + NBD_FLAG_SEND_FUA|NBD_FLAG_SEND_CACHE| + (1 << 15)|(1<<31)); + printf("ioctl(-1, NBD_SET_FLAGS, NBD_FLAG_HAS_FLAGS|NBD_FLAG_READ_ONLY|" + "NBD_FLAG_SEND_FUA|NBD_FLAG_SEND_CACHE|0x80008000)" RVAL_EBADF); + + ioctl(-1, _IOC(_IOC_NONE, 0xab, 0xb, 0), NULL); + printf("ioctl(-1, _IOC(_IOC_NONE, 0xab, 0xb, 0), 0)" RVAL_EBADF); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 361984aa5..69097bfb0 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -118,6 +118,7 @@ ioctl_kvm_run-v ioctl_kvm_run_auxstr_vcpu ioctl_loop ioctl_mtd +ioctl_nbd ioctl_perf ioctl_ptp ioctl_rtc diff --git a/xlat/nbd_ioctl_cmds.in b/xlat/nbd_ioctl_cmds.in new file mode 100644 index 000000000..34f891e3e --- /dev/null +++ b/xlat/nbd_ioctl_cmds.in @@ -0,0 +1,11 @@ +NBD_SET_SOCK _IO( 0xab, 0 ) +NBD_SET_BLKSIZE _IO( 0xab, 1 ) +NBD_SET_SIZE _IO( 0xab, 2 ) +NBD_DO_IT _IO( 0xab, 3 ) +NBD_CLEAR_SOCK _IO( 0xab, 4 ) +NBD_CLEAR_QUE _IO( 0xab, 5 ) +NBD_PRINT_DEBUG _IO( 0xab, 6 ) +NBD_SET_SIZE_BLOCKS _IO( 0xab, 7 ) +NBD_DISCONNECT _IO( 0xab, 8 ) +NBD_SET_TIMEOUT _IO( 0xab, 9 ) +NBD_SET_FLAGS _IO( 0xab, 10) diff --git a/xlat/nbd_ioctl_flags.in b/xlat/nbd_ioctl_flags.in new file mode 100644 index 000000000..60bb07f99 --- /dev/null +++ b/xlat/nbd_ioctl_flags.in @@ -0,0 +1,29 @@ +/* + * Some flags are not defined in <linux/nbd.h>, but are passed anyway. + * These flags are sent from nbd-server to the client, and the client + * passes them to the kernel unmodified after parsing. Both the client + * and the kernel ignore flags unknown to them. + */ + +/* The server supports flags */ +NBD_FLAG_HAS_FLAGS (1 << 0) +/* The export is read-only */ +NBD_FLAG_READ_ONLY (1 << 1) +/* The server supports NBD_CMD_FLUSH */ +NBD_FLAG_SEND_FLUSH (1 << 2) +/* The server supports NBD_CMD_FLAG_FUA (Force Unit Access) */ +NBD_FLAG_SEND_FUA (1 << 3) +/* The export is a rotational medium */ +NBD_FLAG_ROTATIONAL (1 << 4) +/* The server supports NBD_CMD_TRIM */ +NBD_FLAG_SEND_TRIM (1 << 5) +/* The server supports NBD_CMD_WRITE_ZEROES and NBD_CMD_FLAG_NO_HOLE */ +NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) +/* The server supports NBD_CMD_FLAG_DF (don't fragment replies) */ +NBD_FLAG_SEND_DF (1 << 7) +/* The server supports multiple connections */ +NBD_FLAG_CAN_MULTI_CONN (1 << 8) +/* The server supports NBD_CMD_RESIZE (resizing the device) */ +NBD_FLAG_SEND_RESIZE (1 << 9) +/* The server supports NBD_CMD_CACHE */ +NBD_FLAG_SEND_CACHE (1 << 10) |