diff options
author | Don Brady <[email protected]> | 2018-09-02 15:14:01 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2018-09-02 12:14:01 -0700 |
commit | b83a0e2dc1b972e3ae5c0c17b714941b4604dfd6 (patch) | |
tree | 1165e7298a9ca33290ec1988da3acb4cd5065541 /cmd | |
parent | e8bcb693d6a19962291e4429f2dc4ce60693bef7 (diff) |
Add basic zfs ioc input nvpair validation
We want newer versions of libzfs_core to run against an existing
zfs kernel module (i.e. a deferred reboot or module reload after
an update).
Programmatically document, via a zfs_ioc_key_t, the valid arguments
for the ioc commands that rely on nvpair input arguments (i.e. non
legacy commands from libzfs_core). Automatically verify the expected
pairs before dispatching a command.
This initial phase focuses on the non-legacy ioctls. A follow-on
change can address the legacy ioctl input from the zfs_cmd_t.
The zfs_ioc_key_t for zfs_keys_channel_program looks like:
static const zfs_ioc_key_t zfs_keys_channel_program[] = {
{"program", DATA_TYPE_STRING, 0},
{"arg", DATA_TYPE_UNKNOWN, 0},
{"sync", DATA_TYPE_BOOLEAN_VALUE, ZK_OPTIONAL},
{"instrlimit", DATA_TYPE_UINT64, ZK_OPTIONAL},
{"memlimit", DATA_TYPE_UINT64, ZK_OPTIONAL},
};
Introduce four input errors to identify specific input failures
(in addition to generic argument value errors like EINVAL, ERANGE,
EBADF, and E2BIG).
ZFS_ERR_IOC_CMD_UNAVAIL the ioctl number is not supported by kernel
ZFS_ERR_IOC_ARG_UNAVAIL an input argument is not supported by kernel
ZFS_ERR_IOC_ARG_REQUIRED a required input argument is missing
ZFS_ERR_IOC_ARG_BADTYPE an input argument has an invalid type
Reviewed-by: Matthew Ahrens <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Don Brady <[email protected]>
Closes #7780
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/zfs/zfs_main.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index cf2d8f2d5..1a91b031a 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -7238,7 +7238,7 @@ zfs_do_bookmark(int argc, char **argv) fnvlist_free(nvl); if (ret != 0) { - const char *err_msg; + const char *err_msg = NULL; char errbuf[1024]; (void) snprintf(errbuf, sizeof (errbuf), @@ -7265,11 +7265,13 @@ zfs_do_bookmark(int argc, char **argv) err_msg = "dataset does not exist"; break; default: - err_msg = "unknown error"; + (void) zfs_standard_error(g_zfs, ret, errbuf); break; } - (void) fprintf(stderr, "%s: %s\n", errbuf, - dgettext(TEXT_DOMAIN, err_msg)); + if (err_msg != NULL) { + (void) fprintf(stderr, "%s: %s\n", errbuf, + dgettext(TEXT_DOMAIN, err_msg)); + } } return (ret != 0); @@ -7285,7 +7287,7 @@ zfs_do_channel_program(int argc, char **argv) int ret, fd, c; char *progbuf, *filename, *poolname; size_t progsize, progread; - nvlist_t *outnvl; + nvlist_t *outnvl = NULL; uint64_t instrlimit = ZCP_DEFAULT_INSTRLIMIT; uint64_t memlimit = ZCP_DEFAULT_MEMLIMIT; boolean_t sync_flag = B_TRUE, json_output = B_FALSE; @@ -7412,8 +7414,9 @@ zfs_do_channel_program(int argc, char **argv) * falling back on strerror() for an unexpected return code. */ char *errstring = NULL; + const char *msg = gettext("Channel program execution failed"); uint64_t instructions = 0; - if (nvlist_exists(outnvl, ZCP_RET_ERROR)) { + if (outnvl != NULL && nvlist_exists(outnvl, ZCP_RET_ERROR)) { (void) nvlist_lookup_string(outnvl, ZCP_RET_ERROR, &errstring); if (errstring == NULL) @@ -7442,12 +7445,12 @@ zfs_do_channel_program(int argc, char **argv) "programs must be run as root."; break; default: - errstring = strerror(ret); + (void) zfs_standard_error(g_zfs, ret, msg); } } - (void) fprintf(stderr, - gettext("Channel program execution failed:\n%s\n"), - errstring); + if (errstring != NULL) + (void) fprintf(stderr, "%s:\n%s\n", msg, errstring); + if (ret == ETIME && instructions != 0) (void) fprintf(stderr, gettext("%llu Lua instructions\n"), |