Skip to content

Commit 064cfc7

Browse files
warthog618gregkh
authored andcommitted
gpiolib: cdev: Disallow reconfiguration without direction (uAPI v1)
[ Upstream commit 9919cce ] 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]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 70b4889 commit 064cfc7

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
@@ -127,6 +127,10 @@ struct linehandle_state {
127127
GPIOHANDLE_REQUEST_OPEN_DRAIN | \
128128
GPIOHANDLE_REQUEST_OPEN_SOURCE)
129129

130+
#define GPIOHANDLE_REQUEST_DIRECTION_FLAGS \
131+
(GPIOHANDLE_REQUEST_INPUT | \
132+
GPIOHANDLE_REQUEST_OUTPUT)
133+
130134
static int linehandle_validate_flags(u32 flags)
131135
{
132136
/* Return an error if an unknown flag is set */
@@ -207,21 +211,21 @@ static long linehandle_set_config(struct linehandle_state *lh,
207211
if (ret)
208212
return ret;
209213

214+
/* Lines must be reconfigured explicitly as input or output. */
215+
if (!(lflags & GPIOHANDLE_REQUEST_DIRECTION_FLAGS))
216+
return -EINVAL;
217+
210218
for (i = 0; i < lh->num_descs; i++) {
211219
desc = lh->descs[i];
212-
linehandle_flags_to_desc_flags(gcnf.flags, &desc->flags);
220+
linehandle_flags_to_desc_flags(lflags, &desc->flags);
213221

214-
/*
215-
* Lines have to be requested explicitly for input
216-
* or output, else the line will be treated "as is".
217-
*/
218222
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
219223
int val = !!gcnf.default_values[i];
220224

221225
ret = gpiod_direction_output(desc, val);
222226
if (ret)
223227
return ret;
224-
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
228+
} else {
225229
ret = gpiod_direction_input(desc);
226230
if (ret)
227231
return ret;

0 commit comments

Comments
 (0)