Skip to content

Commit 9919cce

Browse files
warthog618Bartosz Golaszewski
authored andcommitted
gpiolib: cdev: Disallow reconfiguration without direction (uAPI v1)
linehandle_set_config() behaves badly when direction is not set. The configuration validation is borrowed from linehandle_create(), where, to verify the intent of the user, the direction must be set to in order to effect a change to the electrical configuration of a line. But, when applied to reconfiguration, that validation does not allow for the unset direction case, making it possible to clear flags set previously without specifying the line direction. Adding to the inconsistency, those changes are not immediately applied by linehandle_set_config(), but will take effect when the line value is next get or set. For example, by requesting a configuration with no flags set, an output line with GPIOHANDLE_REQUEST_ACTIVE_LOW and GPIOHANDLE_REQUEST_OPEN_DRAIN requested could have those flags cleared, inverting the sense of the line and changing the line drive to push-pull on the next line value set. Ensure the intent of the user by disallowing configurations which do not have direction set, returning an error to userspace to indicate that the configuration is invalid. And, for clarity, use lflags, a local copy of gcnf.flags, throughout when dealing with the requested flags, rather than a mixture of both. Fixes: e588bb1 ("gpio: add new SET_CONFIG ioctl() to gpio chardev") Signed-off-by: Kent Gibson <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 8881195 commit 9919cce

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

drivers/gpio/gpiolib-cdev.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ struct linehandle_state {
8989
GPIOHANDLE_REQUEST_OPEN_DRAIN | \
9090
GPIOHANDLE_REQUEST_OPEN_SOURCE)
9191

92+
#define GPIOHANDLE_REQUEST_DIRECTION_FLAGS \
93+
(GPIOHANDLE_REQUEST_INPUT | \
94+
GPIOHANDLE_REQUEST_OUTPUT)
95+
9296
static int linehandle_validate_flags(u32 flags)
9397
{
9498
/* Return an error if an unknown flag is set */
@@ -169,21 +173,21 @@ static long linehandle_set_config(struct linehandle_state *lh,
169173
if (ret)
170174
return ret;
171175

176+
/* Lines must be reconfigured explicitly as input or output. */
177+
if (!(lflags & GPIOHANDLE_REQUEST_DIRECTION_FLAGS))
178+
return -EINVAL;
179+
172180
for (i = 0; i < lh->num_descs; i++) {
173181
desc = lh->descs[i];
174-
linehandle_flags_to_desc_flags(gcnf.flags, &desc->flags);
182+
linehandle_flags_to_desc_flags(lflags, &desc->flags);
175183

176-
/*
177-
* Lines have to be requested explicitly for input
178-
* or output, else the line will be treated "as is".
179-
*/
180184
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
181185
int val = !!gcnf.default_values[i];
182186

183187
ret = gpiod_direction_output(desc, val);
184188
if (ret)
185189
return ret;
186-
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
190+
} else {
187191
ret = gpiod_direction_input(desc);
188192
if (ret)
189193
return ret;

0 commit comments

Comments
 (0)