File 0059-LU-16634-misc-standardize-iocontrol-param-handling.patch of Package lustre_2_12
From 5eae8514f5f1730fe93d55d348400f5ecf681078 Mon Sep 17 00:00:00 2001
From: Andreas Dilger <adilger@whamcloud.com>
Date: Sun, 19 Mar 2023 20:22:10 -0600
Subject: [PATCH] LU-16634 misc: standardize iocontrol param handling
Validate uarg and karg early in iocontrol processing where needed.
This needs kernel interop for 4.20+ kernels for access_ok(), but
this can be checked by #ifdef and does not need an autoconf test.
Fix incorrect definition of OBD_IOC_BARRIER to match reality.
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Reported-by: Tao Lyu <tao.lyu@epfl.ch>
Change-Id: I1a0d2f839949debf346aa15c65b0f407e9ce7057
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50314
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Arshad Hussain <arshad.hussain@aeoncomputing.com>
Reviewed-by: Vitaliy Kuznetsov <vkuznetsov@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
---
lustre/include/lustre_compat.h | 6 +
lustre/include/uapi/linux/lustre/lustre_ioctl.h | 3
lustre/llite/file.c | 76 +++++++++++++-----------
lustre/llite/llite_lib.c | 7 ++
lustre/lod/lod_dev.c | 1
lustre/lov/lov_obd.c | 42 ++++++++++---
lustre/mdc/mdc_request.c | 21 ++++--
lustre/mdd/mdd_device.c | 5 +
lustre/mdt/mdt_handler.c | 39 ++++++------
lustre/mgs/mgs_handler.c | 23 ++++---
lustre/obdclass/class_obd.c | 21 +++---
lustre/obdecho/echo_client.c | 5 +
lustre/ofd/ofd_obd.c | 34 ++++++----
lustre/osc/osc_request.c | 25 ++++++-
lustre/osp/osp_dev.c | 8 ++
lustre/tests/group_lock_test.c | 16 ++---
16 files changed, 212 insertions(+), 120 deletions(-)
--- a/lustre/include/lustre_compat.h
+++ b/lustre/include/lustre_compat.h
@@ -644,6 +644,12 @@ __generic_file_write_iter(struct kiocb *
}
#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
+#ifdef VERIFY_WRITE /* removed in kernel commit v4.20-10979-g96d4f267e40f */
+#define ll_access_ok(ptr, len) access_ok(VERIFY_WRITE, ptr, len)
+#else
+#define ll_access_ok(ptr, len) access_ok(ptr, len)
+#endif
+
static inline void __user *get_vmf_address(struct vm_fault *vmf)
{
#ifdef HAVE_VM_FAULT_ADDRESS
--- a/lustre/include/uapi/linux/lustre/lustre_ioctl.h
+++ b/lustre/include/uapi/linux/lustre/lustre_ioctl.h
@@ -235,7 +235,8 @@ static inline __u32 obd_ioctl_packlen(st
/* lustre/lustre_user.h 240-249 */
/* was LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long) until 2.11 */
-#define OBD_IOC_BARRIER _IOWR('f', 261, OBD_IOC_DATA_TYPE)
+/* OBD_IOC_BARRIER wrongly defined as _IOWR('f', 261, OBD_IOC_DATA_TYPE) */
+#define OBD_IOC_BARRIER _IOWR('g', 5, OBD_IOC_DATA_TYPE)
#define IOC_OSC_SET_ACTIVE _IOWR('h', 21, void *)
--- a/lustre/llite/file.c
+++ b/lustre/llite/file.c
@@ -2103,11 +2103,15 @@ out_lump:
static int ll_file_getstripe(struct inode *inode, void __user *lum, size_t size)
{
- struct lu_env *env;
- __u16 refcheck;
- int rc;
+ struct lu_env *env;
+ __u16 refcheck;
+ int rc;
ENTRY;
+ /* exit before doing any work if pointer is bad */
+ if (unlikely(!ll_access_ok(lum, sizeof(struct lov_user_md))))
+ RETURN(-EFAULT);
+
env = cl_env_get(&refcheck);
if (IS_ERR(env))
RETURN(PTR_ERR(env));
@@ -3175,15 +3179,15 @@ static long ll_file_unlock_lease(struct
bias = MDS_CLOSE_RESYNC_DONE;
break;
case LL_LEASE_LAYOUT_MERGE: {
- int fd;
+ __u32 fdv;
if (ioc->lil_count != 1)
GOTO(out, rc = -EINVAL);
uarg += sizeof(*ioc);
- if (copy_from_user(&fd, uarg, sizeof(__u32)))
+ if (copy_from_user(&fdv, uarg, sizeof(fdv)))
GOTO(out, rc = -EFAULT);
- layout_file = fget(fd);
+ layout_file = fget(fdv);
if (!layout_file)
GOTO(out, rc = -EBADF);
@@ -3194,21 +3198,23 @@ static long ll_file_unlock_lease(struct
data = file_inode(layout_file);
bias = MDS_CLOSE_LAYOUT_MERGE;
break;
- }
+ }
case LL_LEASE_LAYOUT_SPLIT: {
- int fdv;
- int mirror_id;
+ __u32 fdv;
+ __u32 mirror_id;
if (ioc->lil_count != 2)
GOTO(out, rc = -EINVAL);
uarg += sizeof(*ioc);
- if (copy_from_user(&fdv, uarg, sizeof(__u32)))
+ if (copy_from_user(&fdv, uarg, sizeof(fdv)))
GOTO(out, rc = -EFAULT);
- uarg += sizeof(__u32);
- if (copy_from_user(&mirror_id, uarg, sizeof(__u32)))
+ uarg += sizeof(fdv);
+ if (copy_from_user(&mirror_id, uarg, sizeof(mirror_id)))
GOTO(out, rc = -EFAULT);
+ if (mirror_id >= MIRROR_ID_NEG)
+ GOTO(out, rc = -EINVAL);
layout_file = fget(fdv);
if (!layout_file)
@@ -3339,6 +3345,9 @@ ll_file_ioctl(struct file *file, unsigne
if (_IOC_TYPE(cmd) == 'T' || _IOC_TYPE(cmd) == 't') /* tty ioctls */
RETURN(-ENOTTY);
+ /* can't do a generic karg == NULL check here, since it is too noisy and
+ * we need to return -ENOTTY for unsupported ioctls instead of -EINVAL.
+ */
switch (cmd) {
case LL_IOC_GETFLAGS:
/* Get the current value of the file flags */
@@ -3440,6 +3449,9 @@ out:
struct hsm_user_state *hus;
int rc;
+ if (!ll_access_ok(uarg, sizeof(*hus)))
+ RETURN(-EFAULT);
+
OBD_ALLOC_PTR(hus);
if (hus == NULL)
RETURN(-ENOMEM);
@@ -3447,17 +3459,16 @@ out:
op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
LUSTRE_OPC_ANY, hus);
if (IS_ERR(op_data)) {
- OBD_FREE_PTR(hus);
- RETURN(PTR_ERR(op_data));
- }
-
- rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data),
- op_data, NULL);
+ rc = PTR_ERR(op_data);
+ } else {
+ rc = obd_iocontrol(cmd, ll_i2mdexp(inode),
+ sizeof(*op_data), op_data, NULL);
- if (copy_to_user(uarg, hus, sizeof(*hus)))
- rc = -EFAULT;
+ if (copy_to_user(uarg, hus, sizeof(*hus)))
+ rc = -EFAULT;
- ll_finish_md_op_data(op_data);
+ ll_finish_md_op_data(op_data);
+ }
OBD_FREE_PTR(hus);
RETURN(rc);
}
@@ -3469,12 +3480,10 @@ out:
if (hss == NULL)
RETURN(-ENOMEM);
- if (copy_from_user(hss, uarg, sizeof(*hss))) {
- OBD_FREE_PTR(hss);
- RETURN(-EFAULT);
- }
-
- rc = ll_hsm_state_set(inode, hss);
+ if (copy_from_user(hss, uarg, sizeof(*hss)))
+ rc = -EFAULT;
+ else
+ rc = ll_hsm_state_set(inode, hss);
OBD_FREE_PTR(hss);
RETURN(rc);
@@ -3484,6 +3493,9 @@ out:
struct hsm_current_action *hca;
int rc;
+ if (!ll_access_ok(uarg, sizeof(*hca)))
+ RETURN(-EFAULT);
+
OBD_ALLOC_PTR(hca);
if (hca == NULL)
RETURN(-ENOMEM);
@@ -3548,12 +3560,10 @@ out:
if (hui == NULL)
RETURN(-ENOMEM);
- if (copy_from_user(hui, uarg, sizeof(*hui))) {
- OBD_FREE_PTR(hui);
- RETURN(-EFAULT);
- }
-
- rc = ll_hsm_import(inode, file, hui);
+ if (copy_from_user(hui, uarg, sizeof(*hui)))
+ rc = -EFAULT;
+ else
+ rc = ll_hsm_import(inode, file, hui);
OBD_FREE_PTR(hui);
RETURN(rc);
--- a/lustre/llite/llite_lib.c
+++ b/lustre/llite/llite_lib.c
@@ -40,6 +40,7 @@
#include <linux/statfs.h>
#include <linux/time.h>
#include <linux/types.h>
+#include <linux/uaccess.h>
#include <linux/version.h>
#include <linux/mm.h>
#include <linux/user_namespace.h>
@@ -2175,6 +2176,9 @@ int ll_iocontrol(struct inode *inode, st
struct mdt_body *body;
struct md_op_data *op_data;
+ if (!ll_access_ok(uarg, sizeof(int)))
+ RETURN(-EFAULT);
+
op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
LUSTRE_OPC_ANY, NULL);
if (IS_ERR(op_data))
@@ -2250,6 +2254,9 @@ int ll_iocontrol(struct inode *inode, st
case IOC_OBD_STATFS:
RETURN(ll_obd_statfs(inode, uarg));
case LL_IOC_GET_MDTIDX: {
+ if (!ll_access_ok(uarg, sizeof(rc)))
+ RETURN(-EFAULT);
+
rc = ll_get_mdt_idx(inode);
if (rc < 0)
RETURN(rc);
--- a/lustre/lod/lod_dev.c
+++ b/lustre/lod/lod_dev.c
@@ -1987,6 +1987,7 @@ static int lod_obd_disconnect(struct obd
ENTRY;
/* Only disconnect the underlying layers on the final disconnect. */
+
spin_lock(&lod->lod_connects_lock);
lod->lod_connects--;
if (lod->lod_connects != 0) {
--- a/lustre/lov/lov_obd.c
+++ b/lustre/lov/lov_obd.c
@@ -980,15 +980,28 @@ static int lov_iocontrol(unsigned int cm
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
exp->exp_obd->obd_name, cmd, len, karg, uarg);
+ /* exit early for unknown ioctl types */
+ if (unlikely(_IOC_TYPE(cmd) != 'f' && cmd != IOC_OSC_SET_ACTIVE))
+ RETURN(OBD_IOC_DEBUG(D_IOCTL, obd->obd_name, cmd, "unknown",
+ -ENOTTY));
+
+ /* can't do a generic karg == NULL check here, since it is too noisy and
+ * we need to return -ENOTTY for unsupported ioctls instead of -EINVAL.
+ */
switch (cmd) {
case IOC_OBD_STATFS: {
- struct obd_ioctl_data *data = karg;
+ struct obd_ioctl_data *data;
struct obd_device *osc_obd;
struct obd_statfs stat_buf = {0};
struct obd_import *imp;
__u32 index;
__u32 flags;
+ if (unlikely(karg == NULL))
+ RETURN(OBD_IOC_ERROR(obd->obd_name, cmd, "karg=null",
+ -EINVAL));
+ data = karg;
+
memcpy(&index, data->ioc_inlbuf2, sizeof(index));
if (index >= count)
RETURN(-ENODEV);
@@ -1073,10 +1086,15 @@ static int lov_iocontrol(unsigned int cm
break;
}
case OBD_IOC_QUOTACTL: {
- struct if_quotactl *qctl = karg;
+ struct if_quotactl *qctl;
struct lov_tgt_desc *tgt = NULL;
struct obd_quotactl *oqctl;
+ if (unlikely(karg == NULL))
+ RETURN(OBD_IOC_ERROR(obd->obd_name, cmd, "karg=null",
+ -EINVAL));
+ qctl = karg;
+
if (qctl->qc_valid == QC_OSTIDX) {
if (count <= qctl->qc_idx)
RETURN(-EINVAL);
@@ -1147,17 +1165,21 @@ static int lov_iocontrol(unsigned int cm
err);
if (!rc)
rc = err;
+
+ if (err == -ENOTTY)
+ break;
}
} else {
- set = 1;
- }
- }
- if (!set && !rc)
- rc = -EIO;
- }
- }
+ set = 1;
+ }
+ }
+ if (!set && !rc)
+ rc = -EIO;
+ break;
+ }
+ }
- RETURN(rc);
+ RETURN(rc);
}
static int lov_get_info(const struct lu_env *env, struct obd_export *exp,
--- a/lustre/mdc/mdc_request.c
+++ b/lustre/mdc/mdc_request.c
@@ -2065,7 +2065,7 @@ static int mdc_iocontrol(unsigned int cm
void *karg, void __user *uarg)
{
struct obd_device *obd = exp->exp_obd;
- struct obd_ioctl_data *data = karg;
+ struct obd_ioctl_data *data;
struct obd_import *imp = obd->u.cli.cl_import;
int rc;
@@ -2073,6 +2073,19 @@ static int mdc_iocontrol(unsigned int cm
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
obd->obd_name, cmd, len, karg, uarg);
+ /* handle commands that do not need @karg first */
+ switch (cmd) {
+ case LL_IOC_GET_CONNECT_FLAGS:
+ if (copy_to_user(uarg, exp_connect_flags_ptr(exp),
+ sizeof(*exp_connect_flags_ptr(exp))))
+ RETURN(-EFAULT);
+ RETURN(0);
+ }
+
+ if (unlikely(karg == NULL))
+ RETURN(OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL", -EINVAL));
+ data = karg;
+
if (!try_module_get(THIS_MODULE)) {
CERROR("%s: cannot get module '%s'\n", obd->obd_name,
module_name(THIS_MODULE));
@@ -2165,12 +2178,6 @@ static int mdc_iocontrol(unsigned int cm
OBD_FREE_PTR(oqctl);
GOTO(out, rc);
}
- case LL_IOC_GET_CONNECT_FLAGS:
- if (copy_to_user(uarg, exp_connect_flags_ptr(exp),
- sizeof(*exp_connect_flags_ptr(exp))))
- GOTO(out, rc = -EFAULT);
-
- GOTO(out, rc = 0);
case LL_IOC_LOV_SWAP_LAYOUTS:
rc = mdc_ioc_swap_layouts(exp, karg);
GOTO(out, rc);
--- a/lustre/mdd/mdd_device.c
+++ b/lustre/mdd/mdd_device.c
@@ -1924,12 +1924,15 @@ static int mdd_iocontrol(const struct lu
{
struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
struct obd_device *obd = mdd2obd_dev(mdd);
- struct obd_ioctl_data *data = karg;
+ struct obd_ioctl_data *data;
int rc = -EINVAL;
ENTRY;
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK\n",
obd->obd_name, cmd, len, karg);
+ if (unlikely(karg == NULL))
+ RETURN(OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL", rc));
+ data = karg;
/* Doesn't use obd_ioctl_data */
switch (cmd) {
--- a/lustre/mdt/mdt_handler.c
+++ b/lustre/mdt/mdt_handler.c
@@ -6781,9 +6781,10 @@ static int mdt_iocontrol(unsigned int cm
struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
struct dt_device *dt = mdt->mdt_bottom;
struct lu_env env;
+ struct obd_ioctl_data *data;
int rc;
- ENTRY;
+ ENTRY;
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
obd->obd_name, cmd, len, karg, uarg);
@@ -6791,6 +6792,7 @@ static int mdt_iocontrol(unsigned int cm
if (rc)
RETURN(rc);
+ /* handle commands that don't use @karg first */
switch (cmd) {
struct obd_ioctl_data *data = karg;
@@ -6800,39 +6802,41 @@ static int mdt_iocontrol(unsigned int cm
wake_up(&obd->obd_next_transno_waitq);
if (rc == 0)
rc = dt_ro(&env, dt);
- break;
+ GOTO(out, rc);
case OBD_IOC_ABORT_RECOVERY:
- CWARN("%s: Aborting client recovery\n", obd->obd_name);
+ LCONSOLE_WARN("%s: Aborting recovery for device\n",
+ mdt_obd_name(mdt));
obd->obd_abort_recovery = 1;
target_stop_recovery_thread(obd);
rc = 0;
- break;
+ GOTO(out, rc);
+ }
+
+ if (unlikely(karg == NULL)) {
+ OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL", rc = -EINVAL);
+ GOTO(out, rc);
+ }
+ data = karg;
+
+ switch (cmd) {
case OBD_IOC_CHANGELOG_REG:
case OBD_IOC_CHANGELOG_DEREG:
case OBD_IOC_CHANGELOG_CLEAR:
- rc = mdt->mdt_child->md_ops->mdo_iocontrol(&env,
- mdt->mdt_child,
+ rc = mdt->mdt_child->md_ops->mdo_iocontrol(&env, mdt->mdt_child,
cmd, len, karg);
break;
case OBD_IOC_START_LFSCK: {
struct md_device *next = mdt->mdt_child;
- struct obd_ioctl_data *data = karg;
struct lfsck_start_param lsp;
- if (unlikely(data == NULL)) {
- rc = -EINVAL;
- break;
- }
-
lsp.lsp_start = (struct lfsck_start *)(data->ioc_inlbuf1);
lsp.lsp_index_valid = 0;
rc = next->md_ops->mdo_iocontrol(&env, next, cmd, 0, &lsp);
break;
}
case OBD_IOC_STOP_LFSCK: {
- struct md_device *next = mdt->mdt_child;
- struct obd_ioctl_data *data = karg;
- struct lfsck_stop stop;
+ struct md_device *next = mdt->mdt_child;
+ struct lfsck_stop stop;
stop.ls_status = LS_STOPPED;
/* Old lfsck utils may pass NULL @stop. */
@@ -6846,8 +6850,7 @@ static int mdt_iocontrol(unsigned int cm
break;
}
case OBD_IOC_QUERY_LFSCK: {
- struct md_device *next = mdt->mdt_child;
- struct obd_ioctl_data *data = karg;
+ struct md_device *next = mdt->mdt_child;
rc = next->md_ops->mdo_iocontrol(&env, next, cmd, 0,
data->ioc_inlbuf1);
@@ -6877,7 +6880,7 @@ static int mdt_iocontrol(unsigned int cm
rc = OBD_IOC_ERROR(obd->obd_name, cmd, "unrecognized", -ENOTTY);
break;
}
-
+out:
lu_env_fini(&env);
RETURN(rc);
}
--- a/lustre/mgs/mgs_handler.c
+++ b/lustre/mgs/mgs_handler.c
@@ -996,13 +996,16 @@ static int mgs_iocontrol(unsigned int cm
{
struct obd_device *obd = exp->exp_obd;
struct mgs_device *mgs = exp2mgs_dev(exp);
- struct obd_ioctl_data *data = karg;
+ struct obd_ioctl_data *data;
struct lu_env env;
int rc = -EINVAL;
ENTRY;
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
obd->obd_name, cmd, len, karg, uarg);
+ if (unlikely(karg == NULL))
+ RETURN(OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL", rc));
+ data = karg;
rc = lu_env_init(&env, LCT_MG_THREAD);
if (rc)
@@ -1072,8 +1075,8 @@ out_free:
rc = mgs_replace_nids(&env, mgs, data->ioc_inlbuf1,
data->ioc_inlbuf2);
if (rc)
- CERROR("%s: error replacing nids: rc = %d\n",
- obd->obd_name, rc);
+ CERROR("%s: error replacing NIDs for '%s': rc = %d\n",
+ obd->obd_name, data->ioc_inlbuf1, rc);
break;
case OBD_IOC_CLEAR_CONFIGS:
@@ -1124,20 +1127,20 @@ out_free:
break;
case OBD_IOC_LLOG_CANCEL:
case OBD_IOC_LLOG_REMOVE:
- case OBD_IOC_LLOG_CHECK:
- case OBD_IOC_LLOG_INFO:
- case OBD_IOC_LLOG_PRINT: {
- struct llog_ctxt *ctxt;
+ case OBD_IOC_LLOG_CHECK:
+ case OBD_IOC_LLOG_INFO:
+ case OBD_IOC_LLOG_PRINT: {
+ struct llog_ctxt *ctxt;
ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
rc = llog_ioctl(&env, ctxt, cmd, data);
llog_ctxt_put(ctxt);
break;
- }
- default:
+ }
+ default:
rc = OBD_IOC_ERROR(obd->obd_name, cmd, "unrecognized", -ENOTTY);
break;
- }
+ }
out:
lu_env_fini(&env);
RETURN(rc);
--- a/lustre/obdclass/class_obd.c
+++ b/lustre/obdclass/class_obd.c
@@ -278,16 +278,11 @@ int obd_ioctl_getdata(char **buf, int *l
*len = hdr.ioc_len;
data = (struct obd_ioctl_data *)*buf;
- if (copy_from_user(*buf, arg, hdr.ioc_len)) {
- OBD_FREE_LARGE(*buf, hdr.ioc_len);
- RETURN(-EFAULT);
- }
+ if (copy_from_user(*buf, arg, hdr.ioc_len))
+ GOTO(out_free, rc = -EFAULT);
- if (obd_ioctl_is_invalid(data)) {
- CERROR("ioctl not correctly formatted\n");
- OBD_FREE_LARGE(*buf, hdr.ioc_len);
- RETURN(-EINVAL);
- }
+ if (obd_ioctl_is_invalid(data))
+ GOTO(out_free, rc = -EINVAL);
if (data->ioc_inllen1) {
data->ioc_inlbuf1 = &data->ioc_bulk[0];
@@ -308,6 +303,10 @@ int obd_ioctl_getdata(char **buf, int *l
data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
RETURN(0);
+
+out_free:
+ OBD_FREE_LARGE(data, *len);
+ RETURN(rc);
}
EXPORT_SYMBOL(obd_ioctl_getdata);
@@ -320,6 +319,10 @@ int class_handle_ioctl(unsigned int cmd,
ENTRY;
CDEBUG(D_IOCTL, "obdclass: cmd=%x len=%u uarg=%pK\n", cmd, len, uarg);
+ if (unlikely(_IOC_TYPE(cmd) != 'f' && cmd != IOC_OSC_SET_ACTIVE &&
+ cmd != OBD_IOC_BARRIER))
+ RETURN(OBD_IOC_ERROR(obd->obd_name, cmd, "unknown", -ENOTTY));
+
rc = obd_ioctl_getdata(&buf, &len, uarg);
if (rc) {
CERROR("%s: ioctl data error: rc = %d\n", current->comm, rc);
--- a/lustre/obdecho/echo_client.c
+++ b/lustre/obdecho/echo_client.c
@@ -2747,7 +2747,7 @@ echo_client_iocontrol(unsigned int cmd,
struct echo_device *ed = obd2echo_dev(obd);
struct echo_client_obd *ec = ed->ed_ec;
struct echo_object *eco;
- struct obd_ioctl_data *data = karg;
+ struct obd_ioctl_data *data;
struct lu_env *env;
struct obdo *oa;
struct lu_fid fid;
@@ -2760,6 +2760,9 @@ echo_client_iocontrol(unsigned int cmd,
ENTRY;
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
exp->exp_obd->obd_name, cmd, len, karg, uarg);
+ if (unlikely(karg == NULL))
+ RETURN(OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL", rc));
+ data = karg;
oa = &data->ioc_obdo1;
if (!(oa->o_valid & OBD_MD_FLGROUP)) {
--- a/lustre/ofd/ofd_obd.c
+++ b/lustre/ofd/ofd_obd.c
@@ -1258,8 +1258,7 @@ static int ofd_ioc_get_obj_version(const
int rc = 0;
ENTRY;
-
- if (!data->ioc_inlbuf2 || data->ioc_inllen2 != sizeof(version))
+ if (!data || !data->ioc_inlbuf2 || data->ioc_inllen2 != sizeof(version))
GOTO(out, rc = -EINVAL);
if (data->ioc_inlbuf1 && data->ioc_inllen1 == sizeof(fid)) {
@@ -1329,6 +1328,7 @@ static int ofd_iocontrol(unsigned int cm
struct lu_env env;
struct ofd_device *ofd = ofd_exp(exp);
struct obd_device *obd = ofd_obd(ofd);
+ struct obd_ioctl_data *data;
int rc;
ENTRY;
@@ -1338,38 +1338,42 @@ static int ofd_iocontrol(unsigned int cm
if (rc)
RETURN(rc);
+ /* handle commands that don't use @karg first */
+ rc = -EINVAL;
switch (cmd) {
case OBD_IOC_ABORT_RECOVERY:
- CWARN("%s: Aborting recovery\n", obd->obd_name);
+ LCONSOLE_WARN("%s: Aborting recovery\n", obd->obd_name);
obd->obd_abort_recovery = 1;
target_stop_recovery_thread(obd);
- break;
+ GOTO(out, rc);
case OBD_IOC_SYNC:
CDEBUG(D_RPCTRACE, "syncing ost %s\n", obd->obd_name);
rc = dt_sync(&env, ofd->ofd_osd);
- break;
+ GOTO(out, rc);
case OBD_IOC_SET_READONLY:
rc = dt_sync(&env, ofd->ofd_osd);
if (rc == 0)
rc = dt_ro(&env, ofd->ofd_osd);
- break;
+ GOTO(out, rc);
+ }
+
+ if (unlikely(karg == NULL)) {
+ OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL", rc = -EINVAL);
+ GOTO(out, rc);
+ }
+ data = karg;
+
+ switch (cmd) {
case OBD_IOC_START_LFSCK: {
- struct obd_ioctl_data *data = karg;
struct lfsck_start_param lsp;
- if (unlikely(!data)) {
- rc = -EINVAL;
- break;
- }
-
lsp.lsp_start = (struct lfsck_start *)(data->ioc_inlbuf1);
lsp.lsp_index_valid = 0;
rc = lfsck_start(&env, ofd->ofd_osd, &lsp);
break;
}
case OBD_IOC_STOP_LFSCK: {
- struct obd_ioctl_data *data = karg;
- struct lfsck_stop stop;
+ struct lfsck_stop stop;
stop.ls_status = LS_STOPPED;
/* Old lfsck utils may pass NULL @stop. */
@@ -1389,7 +1393,7 @@ static int ofd_iocontrol(unsigned int cm
rc = OBD_IOC_ERROR(obd->obd_name, cmd, "unrecognized", -ENOTTY);
break;
}
-
+out:
lu_env_fini(&env);
RETURN(rc);
}
--- a/lustre/osc/osc_request.c
+++ b/lustre/osc/osc_request.c
@@ -2837,8 +2837,8 @@ static int osc_iocontrol(unsigned int cm
void *karg, void __user *uarg)
{
struct obd_device *obd = exp->exp_obd;
- struct obd_ioctl_data *data = karg;
- int err = 0;
+ struct obd_ioctl_data *data;
+ int err;
ENTRY;
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
@@ -2847,16 +2847,29 @@ static int osc_iocontrol(unsigned int cm
if (!try_module_get(THIS_MODULE)) {
CERROR("%s: cannot get module '%s'\n", obd->obd_name,
module_name(THIS_MODULE));
- return -EINVAL;
+ RETURN(-EINVAL);
}
+
switch (cmd) {
case OBD_IOC_CLIENT_RECOVER:
+ if (unlikely(karg == NULL)) {
+ OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL",
+ err = -EINVAL);
+ break;
+ }
+ data = karg;
err = ptlrpc_recover_import(obd->u.cli.cl_import,
data->ioc_inlbuf1, 0);
if (err > 0)
err = 0;
GOTO(out, err);
case IOC_OSC_SET_ACTIVE:
+ if (unlikely(karg == NULL)) {
+ OBD_IOC_ERROR(obd->obd_name, cmd, "karg=NULL",
+ err = -EINVAL);
+ break;
+ }
+ data = karg;
err = ptlrpc_set_import_active(obd->u.cli.cl_import,
data->ioc_offset);
GOTO(out, err);
@@ -2864,9 +2877,9 @@ static int osc_iocontrol(unsigned int cm
err = ptlrpc_obd_ping(obd);
GOTO(out, err);
default:
- rc = OBD_IOC_DEBUG(D_IOCTL, obd->obd_name, cmd, "unrecognized",
- -ENOTTY);
- GOTO(out, err = -ENOTTY);
+ err = OBD_IOC_DEBUG(D_IOCTL, obd->obd_name, cmd, "unrecognized",
+ -ENOTTY);
+ GOTO(out, err);
}
out:
module_put(THIS_MODULE);
--- a/lustre/osp/osp_dev.c
+++ b/lustre/osp/osp_dev.c
@@ -1648,12 +1648,18 @@ static int osp_iocontrol(unsigned int cm
{
struct obd_device *obd = exp->exp_obd;
struct osp_device *d;
- struct obd_ioctl_data *data = karg;
+ struct obd_ioctl_data *data;
int rc = -EINVAL;
ENTRY;
CDEBUG(D_IOCTL, "%s: cmd=%x len=%u karg=%pK uarg=%pK\n",
exp->exp_obd->obd_name, cmd, len, karg, uarg);
+ if (unlikely(karg == NULL)) {
+ CERROR("%s: iocontrol from '%s' cmd=%x karg=NULL: rc = %d\n",
+ obd->obd_name, current->comm, cmd, rc);
+ RETURN(rc);
+ }
+ data = karg;
LASSERT(obd->obd_lu_dev);
d = lu2osp_dev(obd->obd_lu_dev);
--- a/lustre/tests/group_lock_test.c
+++ b/lustre/tests/group_lock_test.c
@@ -286,23 +286,23 @@ static void helper_test20(int fd)
gid = 1234;
rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
- ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
- rc, strerror(errno));
+ ASSERTF(rc == -1 && (errno == ENOTTY || errno == EINVAL),
+ "unexpected retval: %d %s", rc, strerror(errno));
gid = 0;
rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
- ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
- rc, strerror(errno));
+ ASSERTF(rc == -1 && (errno == ENOTTY || errno == EINVAL),
+ "unexpected retval: %d %s", rc, strerror(errno));
gid = 1;
rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
- ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
- rc, strerror(errno));
+ ASSERTF(rc == -1 && (errno == ENOTTY || errno == EINVAL),
+ "unexpected retval: %d %s", rc, strerror(errno));
gid = -1;
rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
- ASSERTF(rc == -1 && errno == ENOTTY, "unexpected retval: %d %s",
- rc, strerror(errno));
+ ASSERTF(rc == -1 && (errno == ENOTTY || errno == EINVAL),
+ "unexpected retval: %d %s", rc, strerror(errno));
}
/* Test lock / unlock on a directory */