Message ID | 20170404161005.20884-2-lee.jones@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Apr 04, 2017 at 05:10:05PM +0100, Lee Jones wrote: > @@ -237,7 +241,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > if (!(caps & CEC_CAP_RC)) > return adap; > > -#if IS_REACHABLE(CONFIG_RC_CORE) > /* Prepare the RC input device */ > adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); > if (!adap->rc) { The above, coupled with patch 1: +#ifdef CONFIG_RC_CORE struct rc_dev *rc_allocate_device(enum rc_driver_type); +#else +static inline struct rc_dev *rc_allocate_device(int unused) +{ + return ERR_PTR(-EOPNOTSUPP); +} +#endif is really not nice. You claim that this is how stuff is done elsewhere in the kernel, but no, it isn't. Look at debugfs. You're right that debugfs returns an error pointer when it's not configured. However, the debugfs dentry is only ever passed back into the debugfs APIs, it is never dereferenced by the caller. That is not the case here. The effect if your change is that the following dereferences will oops the kernel. This is unacceptable for a feature that is deconfigured.
On Tue, 04 Apr 2017, Russell King - ARM Linux wrote: > On Tue, Apr 04, 2017 at 05:10:05PM +0100, Lee Jones wrote: > > @@ -237,7 +241,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > > if (!(caps & CEC_CAP_RC)) > > return adap; > > > > -#if IS_REACHABLE(CONFIG_RC_CORE) > > /* Prepare the RC input device */ > > adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); > > if (!adap->rc) { > > The above, coupled with patch 1: > > +#ifdef CONFIG_RC_CORE > struct rc_dev *rc_allocate_device(enum rc_driver_type); > +#else > +static inline struct rc_dev *rc_allocate_device(int unused) > +{ > + return ERR_PTR(-EOPNOTSUPP); > +} > +#endif > > is really not nice. You claim that this is how stuff is done elsewhere > in the kernel, but no, it isn't. Look at debugfs. I'm afraid you have entered half way through a conversation, which as caused a misunderstanding. Apologies for not being clear in my commit log. When I say "this is how it's done else where", that is in reference to offering stubs which can be tucked away in a header file, rather than being forced to #if out any functionality which is not available. > You're right that debugfs returns an error pointer when it's not > configured. However, the debugfs dentry is only ever passed back into > the debugfs APIs, it is never dereferenced by the caller. Continued on from my last point: What I do not mean is that this solution is perfect and does not require a review. You are completely correct in what you say, the return values I have used are not suitable. I failed to see how callers were treating the return value. I will carry out due diligence on that point and re-submit as per your request. > That is not the case here. The effect if your change is that the > following dereferences will oops the kernel. This is unacceptable for > a feature that is deconfigured. Fair point Russell. Thanks, will fix.
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index cfe414a..51be8d6 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, return ERR_PTR(-EINVAL); if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) return ERR_PTR(-EINVAL); + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) + caps &= ~CEC_CAP_RC; + adap = kzalloc(sizeof(*adap), GFP_KERNEL); if (!adap) return ERR_PTR(-ENOMEM); + strlcpy(adap->name, name, sizeof(adap->name)); adap->phys_addr = CEC_PHYS_ADDR_INVALID; adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; @@ -237,7 +241,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, if (!(caps & CEC_CAP_RC)) return adap; -#if IS_REACHABLE(CONFIG_RC_CORE) /* Prepare the RC input device */ adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); if (!adap->rc) { @@ -264,9 +267,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap->rc->priv = adap; adap->rc->map_name = RC_MAP_CEC; adap->rc->timeout = MS_TO_NS(100); -#else - adap->capabilities &= ~CEC_CAP_RC; -#endif + return adap; } EXPORT_SYMBOL_GPL(cec_allocate_adapter); @@ -285,7 +286,6 @@ int cec_register_adapter(struct cec_adapter *adap, adap->owner = parent->driver->owner; adap->devnode.dev.parent = parent; -#if IS_REACHABLE(CONFIG_RC_CORE) if (adap->capabilities & CEC_CAP_RC) { adap->rc->dev.parent = parent; res = rc_register_device(adap->rc); @@ -298,15 +298,13 @@ int cec_register_adapter(struct cec_adapter *adap, return res; } } -#endif res = cec_devnode_register(&adap->devnode, adap->owner); if (res) { -#if IS_REACHABLE(CONFIG_RC_CORE) /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); adap->rc = NULL; -#endif + return res; } @@ -337,11 +335,10 @@ void cec_unregister_adapter(struct cec_adapter *adap) if (IS_ERR_OR_NULL(adap)) return; -#if IS_REACHABLE(CONFIG_RC_CORE) /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); adap->rc = NULL; -#endif + debugfs_remove_recursive(adap->cec_dir); cec_devnode_unregister(&adap->devnode); } @@ -357,9 +354,7 @@ void cec_delete_adapter(struct cec_adapter *adap) kthread_stop(adap->kthread); if (adap->kthread_config) kthread_stop(adap->kthread_config); -#if IS_REACHABLE(CONFIG_RC_CORE) rc_free_device(adap->rc); -#endif kfree(adap); } EXPORT_SYMBOL_GPL(cec_delete_adapter);
If a user specifies the use of RC as a capability, they should really be enabling RC Core code. If they do not we WARN() them of this and disable the capability for them. Once we know RC Core code has not been enabled, we can update the user's capabilities and use them as a term of reference for other RC-only calls. This is preferable to having ugly #ifery scattered throughout C code. Most of the functions are actually safe to call, since they sensibly check for a NULL RC pointer before they attempt to deference it. Signed-off-by: Lee Jones <lee.jones@linaro.org> --- drivers/media/cec/cec-core.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)