If an effect is uploaded with file handle equal UINTPTR_MAX assume this effect should be shared and so may be modified using different file handles. Signed-off-by: Angela Czubak <acz@xxxxxxxxxxxx> --- drivers/input/ff-core.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index fa8d1a466014..1a9a5401acb5 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -34,6 +34,23 @@ static int check_effect_access(struct ff_device *ff, int effect_id, return 0; } +/* + * Check that the effect_id is a valid effect and whether the effect + * is shared + */ +static int check_effect_shared(struct ff_device *ff, int effect_id) +{ + if (effect_id < 0 || effect_id >= ff->max_effects || + !ff->effect_owners[effect_id]) + return -EINVAL; + + /* Shared effect */ + if (ff->effect_owners[effect_id] == (struct file *)UINTPTR_MAX) + return 0; + + return -EACCES; +} + /* * Checks whether 2 effects can be combined together */ @@ -139,8 +156,11 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, id = effect->id; ret = check_effect_access(ff, id, file); - if (ret) - goto out; + if (ret) { + ret = check_effect_shared(ff, id); + if (ret) + goto out; + } old = &ff->effects[id]; @@ -174,21 +194,29 @@ static int erase_effect(struct input_dev *dev, int effect_id, { struct ff_device *ff = dev->ff; int error; + bool shared = false; error = check_effect_access(ff, effect_id, file); - if (error) - return error; + if (error) { + error = check_effect_shared(ff, effect_id); + if (!error) + shared = true; + else + return error; + } spin_lock_irq(&dev->event_lock); ff->playback(dev, effect_id, 0); - ff->effect_owners[effect_id] = NULL; + if (!shared) + ff->effect_owners[effect_id] = NULL; spin_unlock_irq(&dev->event_lock); if (ff->erase) { error = ff->erase(dev, effect_id); if (error) { spin_lock_irq(&dev->event_lock); - ff->effect_owners[effect_id] = file; + if (!shared) + ff->effect_owners[effect_id] = file; spin_unlock_irq(&dev->event_lock); return error; -- 2.36.0.550.gb090851708-goog