* [PATCH 0/2] Add a driver for the ChromeOS snooping protection sensor (HPS) @ 2022-01-27 8:35 Sami Kyöstilä 2022-01-27 8:35 ` [PATCH 1/2] drivers/misc: add a driver for HPS Sami Kyöstilä 2022-01-27 8:35 ` [PATCH 2/2] drivers/misc: add transfer ioctl " Sami Kyöstilä 0 siblings, 2 replies; 15+ messages in thread From: Sami Kyöstilä @ 2022-01-27 8:35 UTC (permalink / raw) To: LKML; +Cc: dtor, evanbenn, arnd, gregkh, Sami Kyöstilä This series adds a driver for the ChromeOS snooping protection sensor (a.k.a. HPS) device, attached on the I2C bus. The sensor is a hardware-isolated module which reports a high-level presence signal, e.g., whether there is person in front of the computer or not. The driver exposes the device to userspace as a character device, which can be used to send and receive messages to the sensor. The driver automatically turns power off to the sensor unless a process is More information about HPS, its firmware and communication protocol can be found at https://chromium.googlesource.com/chromiumos/platform/hps-firmware. Sami Kyöstilä (2): drivers/misc: add a driver for HPS drivers/misc: add transfer ioctl for HPS MAINTAINERS | 7 + drivers/misc/Kconfig | 10 ++ drivers/misc/Makefile | 1 + drivers/misc/hps-i2c.c | 304 +++++++++++++++++++++++++++++++++++++++ include/uapi/linux/hps.h | 20 +++ 5 files changed, 342 insertions(+) create mode 100644 drivers/misc/hps-i2c.c create mode 100644 include/uapi/linux/hps.h -- 2.35.0.rc0.227.g00780c9af4-goog ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] drivers/misc: add a driver for HPS 2022-01-27 8:35 [PATCH 0/2] Add a driver for the ChromeOS snooping protection sensor (HPS) Sami Kyöstilä @ 2022-01-27 8:35 ` Sami Kyöstilä 2022-01-27 9:40 ` Greg KH 2022-02-18 17:20 ` Pavel Machek 2022-01-27 8:35 ` [PATCH 2/2] drivers/misc: add transfer ioctl " Sami Kyöstilä 1 sibling, 2 replies; 15+ messages in thread From: Sami Kyöstilä @ 2022-01-27 8:35 UTC (permalink / raw) To: LKML; +Cc: dtor, evanbenn, arnd, gregkh, Sami Kyöstilä This patch introduces a driver for the ChromeOS snooping protection sensor (aka. HPS). The driver supports a sensor connected to the I2C bus and identified as "GOOG0020" in the ACPI tables. When loaded, the driver exports the sensor to userspace through a character device. This initial version of the device only supports power management, i.e., communicating with the sensor must be done through I2C from userspace. Power management is implemented by enabling the respective power GPIO while at least one userspace process holds an open fd on the character device. By default, the device is powered down if there are no active clients. Note that the driver makes no effort to preserve the state of the sensor between power down and power up events. Userspace is responsible for reinitializing any needed state once power has been restored. The device firmware, I2C protocol and other documentation is available at https://chromium.googlesource.com/chromiumos/platform/hps-firmware. Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> --- MAINTAINERS | 6 ++ drivers/misc/Kconfig | 10 ++ drivers/misc/Makefile | 1 + drivers/misc/hps-i2c.c | 223 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 drivers/misc/hps-i2c.c diff --git a/MAINTAINERS b/MAINTAINERS index ea3e6c914384..9dea4b8c2ab5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8798,6 +8798,12 @@ S: Maintained W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi F: fs/hpfs/ +HPS (ChromeOS snooping protection sensor) DRIVER +M: Sami Kyöstilä <skyostil@chromium.org> +R: Evan Benn <evanbenn@chromium.org> +S: Maintained +F: drivers/misc/hps-i2c.c + HSI SUBSYSTEM M: Sebastian Reichel <sre@kernel.org> S: Maintained diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0f5a49fc7c9e..b48b7803f537 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -244,6 +244,16 @@ config HP_ILO To compile this driver as a module, choose M here: the module will be called hpilo. +config HPS_I2C + tristate "ChromeOS HPS device support" + depends on HID && I2C && PM + help + Say Y here if you want to enable support for the ChromeOS + anti-snooping sensor (HPS), attached via I2C. The driver supports a + sensor connected to the I2C bus and exposes it as a character device. + To save power, the sensor is automatically powered down when no + clients are accessing it. + config QCOM_COINCELL tristate "Qualcomm coincell charger support" depends on MFD_SPMI_PMIC || COMPILE_TEST diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index a086197af544..162a7d530dab 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o obj-$(CONFIG_GEHC_ACHC) += gehc-achc.o obj-$(CONFIG_HP_ILO) += hpilo.o +obj-$(CONFIG_HPS_I2C) += hps-i2c.o obj-$(CONFIG_APDS9802ALS) += apds9802als.o obj-$(CONFIG_ISL29003) += isl29003.o obj-$(CONFIG_ISL29020) += isl29020.o diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c new file mode 100644 index 000000000000..fe9f073b0352 --- /dev/null +++ b/drivers/misc/hps-i2c.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for the ChromeOS anti-snooping sensor (HPS), attached via I2C. + * + * The driver exposes HPS as a character device, although currently no read or + * write operations are supported. Instead, the driver only controls the power + * state of the sensor, keeping it on only while userspace holds an open file + * descriptor to the HPS device. + * + * Copyright 2022 Google LLC. + */ + +#include <linux/acpi.h> +#include <linux/cdev.h> +#include <linux/fs.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> + +#define HPS_ACPI_ID "GOOG0020" +#define HPS_MAX_DEVICES 1 + +struct hps_drvdata { + struct i2c_client *client; + + struct cdev cdev; + struct class *cdev_class; + + struct gpio_desc *enable_gpio; +}; + +static int hps_dev_major; + +static void hps_power_on(struct hps_drvdata *hps) +{ + if (!IS_ERR_OR_NULL(hps->enable_gpio)) + gpiod_set_value_cansleep(hps->enable_gpio, 1); +} + +static void hps_power_off(struct hps_drvdata *hps) +{ + if (!IS_ERR_OR_NULL(hps->enable_gpio)) + gpiod_set_value_cansleep(hps->enable_gpio, 0); +} + +static void hps_unload(void *drv_data) +{ + struct hps_drvdata *hps = drv_data; + + hps_power_on(hps); +} + +static int hps_open(struct inode *inode, struct file *file) +{ + struct hps_drvdata *hps = container_of(inode->i_cdev, struct hps_drvdata, cdev); + struct device *dev = &hps->client->dev; + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + goto pm_get_fail; + return 0; + +pm_get_fail: + pm_runtime_put(dev); + pm_runtime_disable(dev); + return ret; +} + +static int hps_release(struct inode *inode, struct file *file) +{ + struct hps_drvdata *hps = container_of(inode->i_cdev, struct hps_drvdata, cdev); + struct device *dev = &hps->client->dev; + int ret; + + ret = pm_runtime_put(dev); + if (ret < 0) + goto pm_put_fail; + return 0; + +pm_put_fail: + pm_runtime_disable(dev); + return ret; +} + +const struct file_operations hps_fops = { + .owner = THIS_MODULE, + .open = hps_open, + .release = hps_release, +}; + +static int hps_i2c_probe(struct i2c_client *client) +{ + struct hps_drvdata *hps; + int ret = 0; + dev_t hps_dev; + + hps = devm_kzalloc(&client->dev, sizeof(*hps), GFP_KERNEL); + if (!hps) + return -ENOMEM; + + i2c_set_clientdata(client, hps); + hps->client = client; + hps->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(hps->enable_gpio)) { + ret = PTR_ERR(hps->enable_gpio); + dev_err(&client->dev, "failed to get enable gpio: %d\n", ret); + return ret; + } + + ret = devm_add_action(&client->dev, &hps_unload, hps); + if (ret) { + dev_err(&client->dev, + "failed to install unload action: %d\n", ret); + return ret; + } + + ret = alloc_chrdev_region(&hps_dev, 0, HPS_MAX_DEVICES, "hps"); + if (ret) { + dev_err(&client->dev, + "failed to register char dev: %d\n", ret); + return ret; + } + hps_dev_major = MAJOR(hps_dev); + cdev_init(&hps->cdev, &hps_fops); + ret = cdev_add(&hps->cdev, hps_dev, 1); + if (ret) { + dev_err(&client->dev, "cdev_add() failed: %d\n", ret); + goto cdev_add_failed; + } + + hps->cdev_class = class_create(THIS_MODULE, "hps"); + if (IS_ERR(hps->cdev_class)) { + dev_err(&client->dev, "class_create() failed: %d\n", ret); + goto class_create_failed; + } + device_create(hps->cdev_class, NULL, hps_dev, NULL, "hps"); + + hps_power_off(hps); + pm_runtime_enable(&client->dev); + return ret; + +class_create_failed: + ret = PTR_ERR(hps->cdev_class); + hps->cdev_class = NULL; + +cdev_add_failed: + unregister_chrdev_region(MKDEV(hps_dev_major, 0), HPS_MAX_DEVICES); + hps_dev_major = 0; + return ret; +} + +static int hps_i2c_remove(struct i2c_client *client) +{ + struct hps_drvdata *hps = i2c_get_clientdata(client); + + pm_runtime_disable(&client->dev); + if (hps_dev_major) { + dev_t hps_dev = MKDEV(hps_dev_major, 0); + + device_destroy(hps->cdev_class, hps_dev); + class_destroy(hps->cdev_class); + hps->cdev_class = NULL; + + cdev_del(&hps->cdev); + unregister_chrdev_region(hps_dev, HPS_MAX_DEVICES); + hps_dev_major = 0; + } + return 0; +} + +static int hps_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct hps_drvdata *hps = i2c_get_clientdata(client); + + hps_power_off(hps); + return 0; +} + +static int hps_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct hps_drvdata *hps = i2c_get_clientdata(client); + + hps_power_on(hps); + return 0; +} +static UNIVERSAL_DEV_PM_OPS(hps_pm_ops, hps_suspend, hps_resume, NULL); + +static const struct i2c_device_id hps_i2c_id[] = { + { "hps", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, hps_i2c_id); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id hps_acpi_id[] = { + { HPS_ACPI_ID, 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, hps_acpi_id); +#endif /* CONFIG_ACPI */ + +static struct i2c_driver hps_i2c_driver = { + .probe_new = hps_i2c_probe, + .remove = hps_i2c_remove, + .id_table = hps_i2c_id, + .driver = { + .name = "hps", + .pm = &hps_pm_ops, +#ifdef CONFIG_ACPI + .acpi_match_table = ACPI_PTR(hps_acpi_id), +#endif + }, +}; +module_i2c_driver(hps_i2c_driver); + +MODULE_ALIAS("acpi:" HPS_ACPI_ID); +MODULE_AUTHOR("Sami Kyöstilä <skyostil@chromium.org>"); +MODULE_DESCRIPTION("Driver for ChromeOS HPS"); +MODULE_LICENSE("GPL"); -- 2.35.0.rc0.227.g00780c9af4-goog ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] drivers/misc: add a driver for HPS 2022-01-27 8:35 ` [PATCH 1/2] drivers/misc: add a driver for HPS Sami Kyöstilä @ 2022-01-27 9:40 ` Greg KH 2022-01-28 7:41 ` Sami Kyostila 2022-02-18 17:20 ` Pavel Machek 1 sibling, 1 reply; 15+ messages in thread From: Greg KH @ 2022-01-27 9:40 UTC (permalink / raw) To: Sami Kyöstilä; +Cc: LKML, dtor, evanbenn, arnd On Thu, Jan 27, 2022 at 07:35:44PM +1100, Sami Kyöstilä wrote: > This patch introduces a driver for the ChromeOS snooping protection > sensor (aka. HPS). The driver supports a sensor connected to the I2C bus > and identified as "GOOG0020" in the ACPI tables. > > When loaded, the driver exports the sensor to userspace through a > character device. This initial version of the device only supports power > management, i.e., communicating with the sensor must be done through I2C > from userspace. > > Power management is implemented by enabling the respective power GPIO > while at least one userspace process holds an open fd on the character > device. By default, the device is powered down if there are no active > clients. > > Note that the driver makes no effort to preserve the state of the sensor > between power down and power up events. Userspace is responsible for > reinitializing any needed state once power has been restored. > > The device firmware, I2C protocol and other documentation is available > at https://chromium.googlesource.com/chromiumos/platform/hps-firmware. How about a userspace tool that interacts with this new ioctl interface as well so that we can understand how the driver is supposed to work? > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > --- > > MAINTAINERS | 6 ++ > drivers/misc/Kconfig | 10 ++ > drivers/misc/Makefile | 1 + > drivers/misc/hps-i2c.c | 223 +++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 240 insertions(+) > create mode 100644 drivers/misc/hps-i2c.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index ea3e6c914384..9dea4b8c2ab5 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -8798,6 +8798,12 @@ S: Maintained > W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi > F: fs/hpfs/ > > +HPS (ChromeOS snooping protection sensor) DRIVER > +M: Sami Kyöstilä <skyostil@chromium.org> > +R: Evan Benn <evanbenn@chromium.org> > +S: Maintained > +F: drivers/misc/hps-i2c.c > + > HSI SUBSYSTEM > M: Sebastian Reichel <sre@kernel.org> > S: Maintained > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig > index 0f5a49fc7c9e..b48b7803f537 100644 > --- a/drivers/misc/Kconfig > +++ b/drivers/misc/Kconfig > @@ -244,6 +244,16 @@ config HP_ILO > To compile this driver as a module, choose M here: the > module will be called hpilo. > > +config HPS_I2C > + tristate "ChromeOS HPS device support" > + depends on HID && I2C && PM > + help > + Say Y here if you want to enable support for the ChromeOS > + anti-snooping sensor (HPS), attached via I2C. The driver supports a > + sensor connected to the I2C bus and exposes it as a character device. > + To save power, the sensor is automatically powered down when no > + clients are accessing it. > + > config QCOM_COINCELL > tristate "Qualcomm coincell charger support" > depends on MFD_SPMI_PMIC || COMPILE_TEST > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile > index a086197af544..162a7d530dab 100644 > --- a/drivers/misc/Makefile > +++ b/drivers/misc/Makefile > @@ -26,6 +26,7 @@ obj-$(CONFIG_SGI_GRU) += sgi-gru/ > obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o > obj-$(CONFIG_GEHC_ACHC) += gehc-achc.o > obj-$(CONFIG_HP_ILO) += hpilo.o > +obj-$(CONFIG_HPS_I2C) += hps-i2c.o > obj-$(CONFIG_APDS9802ALS) += apds9802als.o > obj-$(CONFIG_ISL29003) += isl29003.o > obj-$(CONFIG_ISL29020) += isl29020.o > diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c > new file mode 100644 > index 000000000000..fe9f073b0352 > --- /dev/null > +++ b/drivers/misc/hps-i2c.c > @@ -0,0 +1,223 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Driver for the ChromeOS anti-snooping sensor (HPS), attached via I2C. > + * > + * The driver exposes HPS as a character device, although currently no read or > + * write operations are supported. Instead, the driver only controls the power > + * state of the sensor, keeping it on only while userspace holds an open file > + * descriptor to the HPS device. > + * > + * Copyright 2022 Google LLC. > + */ > + > +#include <linux/acpi.h> > +#include <linux/cdev.h> > +#include <linux/fs.h> > +#include <linux/gpio/consumer.h> > +#include <linux/i2c.h> > +#include <linux/module.h> > +#include <linux/pm_runtime.h> > + > +#define HPS_ACPI_ID "GOOG0020" > +#define HPS_MAX_DEVICES 1 > + > +struct hps_drvdata { > + struct i2c_client *client; > + > + struct cdev cdev; > + struct class *cdev_class; As you only have 1 device, please just use the miscdev interface, not the chardev interface. Makes your code much smaller and easier to review and maintain over time and does not "burn" a whole major number for this tiny driver. thanks, greg k-h ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] drivers/misc: add a driver for HPS 2022-01-27 9:40 ` Greg KH @ 2022-01-28 7:41 ` Sami Kyostila 2022-01-28 9:36 ` Greg KH 0 siblings, 1 reply; 15+ messages in thread From: Sami Kyostila @ 2022-01-28 7:41 UTC (permalink / raw) To: Greg KH; +Cc: LKML, dtor, evanbenn, arnd to 27. tammik. 2022 klo 20.40 Greg KH (gregkh@linuxfoundation.org) kirjoitti: > > On Thu, Jan 27, 2022 at 07:35:44PM +1100, Sami Kyöstilä wrote: > > This patch introduces a driver for the ChromeOS snooping protection > > sensor (aka. HPS). The driver supports a sensor connected to the I2C bus > > and identified as "GOOG0020" in the ACPI tables. > > > > When loaded, the driver exports the sensor to userspace through a > > character device. This initial version of the device only supports power > > management, i.e., communicating with the sensor must be done through I2C > > from userspace. > > > > Power management is implemented by enabling the respective power GPIO > > while at least one userspace process holds an open fd on the character > > device. By default, the device is powered down if there are no active > > clients. > > > > Note that the driver makes no effort to preserve the state of the sensor > > between power down and power up events. Userspace is responsible for > > reinitializing any needed state once power has been restored. > > > > The device firmware, I2C protocol and other documentation is available > > at https://chromium.googlesource.com/chromiumos/platform/hps-firmware. > > How about a userspace tool that interacts with this new ioctl interface > as well so that we can understand how the driver is supposed to work? Sure, here's a small example that shows how to read a magic register value from the device: https://gist.github.com/skyostil/13d60a288919d18d00b20e81dfe018cd (Let me know if you'd prefer this to be checked into the tree somewhere.) Here's also a patch that makes the production daemon use this interface: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3353640 > > > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > > --- > > > > MAINTAINERS | 6 ++ > > drivers/misc/Kconfig | 10 ++ > > drivers/misc/Makefile | 1 + > > drivers/misc/hps-i2c.c | 223 +++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 240 insertions(+) > > create mode 100644 drivers/misc/hps-i2c.c > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index ea3e6c914384..9dea4b8c2ab5 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -8798,6 +8798,12 @@ S: Maintained > > W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi > > F: fs/hpfs/ > > > > +HPS (ChromeOS snooping protection sensor) DRIVER > > +M: Sami Kyöstilä <skyostil@chromium.org> > > +R: Evan Benn <evanbenn@chromium.org> > > +S: Maintained > > +F: drivers/misc/hps-i2c.c > > + > > HSI SUBSYSTEM > > M: Sebastian Reichel <sre@kernel.org> > > S: Maintained > > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig > > index 0f5a49fc7c9e..b48b7803f537 100644 > > --- a/drivers/misc/Kconfig > > +++ b/drivers/misc/Kconfig > > @@ -244,6 +244,16 @@ config HP_ILO > > To compile this driver as a module, choose M here: the > > module will be called hpilo. > > > > +config HPS_I2C > > + tristate "ChromeOS HPS device support" > > + depends on HID && I2C && PM > > + help > > + Say Y here if you want to enable support for the ChromeOS > > + anti-snooping sensor (HPS), attached via I2C. The driver supports a > > + sensor connected to the I2C bus and exposes it as a character device. > > + To save power, the sensor is automatically powered down when no > > + clients are accessing it. > > + > > config QCOM_COINCELL > > tristate "Qualcomm coincell charger support" > > depends on MFD_SPMI_PMIC || COMPILE_TEST > > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile > > index a086197af544..162a7d530dab 100644 > > --- a/drivers/misc/Makefile > > +++ b/drivers/misc/Makefile > > @@ -26,6 +26,7 @@ obj-$(CONFIG_SGI_GRU) += sgi-gru/ > > obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o > > obj-$(CONFIG_GEHC_ACHC) += gehc-achc.o > > obj-$(CONFIG_HP_ILO) += hpilo.o > > +obj-$(CONFIG_HPS_I2C) += hps-i2c.o > > obj-$(CONFIG_APDS9802ALS) += apds9802als.o > > obj-$(CONFIG_ISL29003) += isl29003.o > > obj-$(CONFIG_ISL29020) += isl29020.o > > diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c > > new file mode 100644 > > index 000000000000..fe9f073b0352 > > --- /dev/null > > +++ b/drivers/misc/hps-i2c.c > > @@ -0,0 +1,223 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Driver for the ChromeOS anti-snooping sensor (HPS), attached via I2C. > > + * > > + * The driver exposes HPS as a character device, although currently no read or > > + * write operations are supported. Instead, the driver only controls the power > > + * state of the sensor, keeping it on only while userspace holds an open file > > + * descriptor to the HPS device. > > + * > > + * Copyright 2022 Google LLC. > > + */ > > + > > +#include <linux/acpi.h> > > +#include <linux/cdev.h> > > +#include <linux/fs.h> > > +#include <linux/gpio/consumer.h> > > +#include <linux/i2c.h> > > +#include <linux/module.h> > > +#include <linux/pm_runtime.h> > > + > > +#define HPS_ACPI_ID "GOOG0020" > > +#define HPS_MAX_DEVICES 1 > > + > > +struct hps_drvdata { > > + struct i2c_client *client; > > + > > + struct cdev cdev; > > + struct class *cdev_class; > > As you only have 1 device, please just use the miscdev interface, not > the chardev interface. Makes your code much smaller and easier to > review and maintain over time and does not "burn" a whole major number > for this tiny driver. Will do, thanks for the tip! > > thanks, > > greg k-h - Sami ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] drivers/misc: add a driver for HPS 2022-01-28 7:41 ` Sami Kyostila @ 2022-01-28 9:36 ` Greg KH 0 siblings, 0 replies; 15+ messages in thread From: Greg KH @ 2022-01-28 9:36 UTC (permalink / raw) To: Sami Kyostila; +Cc: LKML, dtor, evanbenn, arnd On Fri, Jan 28, 2022 at 06:41:25PM +1100, Sami Kyostila wrote: > to 27. tammik. 2022 klo 20.40 Greg KH (gregkh@linuxfoundation.org) kirjoitti: > > > > On Thu, Jan 27, 2022 at 07:35:44PM +1100, Sami Kyöstilä wrote: > > > This patch introduces a driver for the ChromeOS snooping protection > > > sensor (aka. HPS). The driver supports a sensor connected to the I2C bus > > > and identified as "GOOG0020" in the ACPI tables. > > > > > > When loaded, the driver exports the sensor to userspace through a > > > character device. This initial version of the device only supports power > > > management, i.e., communicating with the sensor must be done through I2C > > > from userspace. > > > > > > Power management is implemented by enabling the respective power GPIO > > > while at least one userspace process holds an open fd on the character > > > device. By default, the device is powered down if there are no active > > > clients. > > > > > > Note that the driver makes no effort to preserve the state of the sensor > > > between power down and power up events. Userspace is responsible for > > > reinitializing any needed state once power has been restored. > > > > > > The device firmware, I2C protocol and other documentation is available > > > at https://chromium.googlesource.com/chromiumos/platform/hps-firmware. > > > > How about a userspace tool that interacts with this new ioctl interface > > as well so that we can understand how the driver is supposed to work? > > Sure, here's a small example that shows how to read a magic register > value from the device: > https://gist.github.com/skyostil/13d60a288919d18d00b20e81dfe018cd > > (Let me know if you'd prefer this to be checked into the tree somewhere.) It should be somewhere so we know where to look and how this works and who to complain to when it needs to be changed :) thanks, greg k-h ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] drivers/misc: add a driver for HPS 2022-01-27 8:35 ` [PATCH 1/2] drivers/misc: add a driver for HPS Sami Kyöstilä 2022-01-27 9:40 ` Greg KH @ 2022-02-18 17:20 ` Pavel Machek 1 sibling, 0 replies; 15+ messages in thread From: Pavel Machek @ 2022-02-18 17:20 UTC (permalink / raw) To: Sami Kyöstilä; +Cc: LKML, dtor, evanbenn, arnd, gregkh [-- Attachment #1: Type: text/plain, Size: 702 bytes --] Hi! > +config HPS_I2C > + tristate "ChromeOS HPS device support" > + depends on HID && I2C && PM > + help > + Say Y here if you want to enable support for the ChromeOS > + anti-snooping sensor (HPS), attached via I2C. The driver supports a > + sensor connected to the I2C bus and exposes it as a character device. > + To save power, the sensor is automatically powered down when no > + clients are accessing it. > + We don't need to know about power management here; but it would be good to have explanation what anti-snooping sensor actually does. Is it camera detecting user or what? Best regards, Pavel -- http://www.livejournal.com/~pavelmachek [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-27 8:35 [PATCH 0/2] Add a driver for the ChromeOS snooping protection sensor (HPS) Sami Kyöstilä 2022-01-27 8:35 ` [PATCH 1/2] drivers/misc: add a driver for HPS Sami Kyöstilä @ 2022-01-27 8:35 ` Sami Kyöstilä 2022-01-27 9:41 ` Greg KH 2022-01-27 22:39 ` Randy Dunlap 1 sibling, 2 replies; 15+ messages in thread From: Sami Kyöstilä @ 2022-01-27 8:35 UTC (permalink / raw) To: LKML; +Cc: dtor, evanbenn, arnd, gregkh, Sami Kyöstilä This patch adds an ioctl operation for sending and receiving data from the ChromeOS snooping protection sensor (a.k.a., HPS). This allows userspace programs to perform a combined read/write I2C transaction through a single syscall. The I2C wire protocol for the device is documented at: https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ refs/heads/main/docs/host_device_i2c_protocol.md Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> --- MAINTAINERS | 1 + drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/hps.h | 20 ++++++++++ 3 files changed, 102 insertions(+) create mode 100644 include/uapi/linux/hps.h diff --git a/MAINTAINERS b/MAINTAINERS index 9dea4b8c2ab5..d5fc066fdbc2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8803,6 +8803,7 @@ M: Sami Kyöstilä <skyostil@chromium.org> R: Evan Benn <evanbenn@chromium.org> S: Maintained F: drivers/misc/hps-i2c.c +F: include/uapi/linux/hps.h HSI SUBSYSTEM M: Sebastian Reichel <sre@kernel.org> diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c index fe9f073b0352..748ead49d678 100644 --- a/drivers/misc/hps-i2c.c +++ b/drivers/misc/hps-i2c.c @@ -17,9 +17,11 @@ #include <linux/i2c.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <uapi/linux/hps.h> #define HPS_ACPI_ID "GOOG0020" #define HPS_MAX_DEVICES 1 +#define HPS_MAX_MSG_SIZE 8192 struct hps_drvdata { struct i2c_client *client; @@ -60,6 +62,8 @@ static int hps_open(struct inode *inode, struct file *file) ret = pm_runtime_get_sync(dev); if (ret < 0) goto pm_get_fail; + + file->private_data = hps->client; return 0; pm_get_fail: @@ -84,10 +88,87 @@ static int hps_release(struct inode *inode, struct file *file) return ret; } +static int hps_do_ioctl_transfer(struct i2c_client *client, + struct hps_transfer_ioctl_data *args) +{ + int ret; + int nmsg = 0; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = client->flags, + }, + { + .addr = client->addr, + .flags = client->flags, + }, + }; + + if (args->isize) { + msgs[nmsg].len = args->isize; + msgs[nmsg].buf = memdup_user(args->ibuf, args->isize); + if (IS_ERR(msgs[nmsg].buf)) { + ret = PTR_ERR(msgs[nmsg].buf); + goto memdup_fail; + } + nmsg++; + } + + if (args->osize) { + msgs[nmsg].len = args->osize; + msgs[nmsg].buf = memdup_user(args->obuf, args->osize); + msgs[nmsg].flags |= I2C_M_RD; + if (IS_ERR(msgs[nmsg].buf)) { + ret = PTR_ERR(msgs[nmsg].buf); + goto memdup_fail; + } + nmsg++; + } + + ret = i2c_transfer(client->adapter, &msgs[0], nmsg); + if (ret > 0 && args->osize) { + if (copy_to_user(args->obuf, msgs[nmsg - 1].buf, ret)) + ret = -EFAULT; + } + +memdup_fail: + while (nmsg > 0) + kfree(msgs[--nmsg].buf); + return ret; +} + +static long hps_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct i2c_client *client = file->private_data; + + switch (cmd) { + case HPS_IOC_TRANSFER: { + struct hps_transfer_ioctl_data args; + + if (copy_from_user(&args, + (struct hps_transfer_ioctl_data __user *)arg, + sizeof(args))) { + return -EFAULT; + } + + if (!args.isize && !args.osize) + return -EINVAL; + if (args.isize > HPS_MAX_MSG_SIZE || args.osize > HPS_MAX_MSG_SIZE) + return -EINVAL; + + return hps_do_ioctl_transfer(client, &args); + } + default: + return -EFAULT; + } +} + + const struct file_operations hps_fops = { .owner = THIS_MODULE, .open = hps_open, .release = hps_release, + .unlocked_ioctl = hps_ioctl, }; static int hps_i2c_probe(struct i2c_client *client) diff --git a/include/uapi/linux/hps.h b/include/uapi/linux/hps.h new file mode 100644 index 000000000000..2c1bd174cd02 --- /dev/null +++ b/include/uapi/linux/hps.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright 2022 Google LLC. + */ + +#ifndef _UAPI_HPS_H +#define _UAPI_HPS_H + +#include <linux/types.h> + +#define HPS_IOC_TRANSFER _IOWR('h', 0x01, struct hps_transfer_ioctl_data) + +struct hps_transfer_ioctl_data { + __u32 isize; /* Number of bytes to send */ + unsigned char __user *ibuf; /* Input buffer */ + __u32 osize; /* Number of bytes to receive */ + unsigned char __user *obuf; /* Output buffer */ +}; + +#endif /* _UAPI_HPS_H */ -- 2.35.0.rc0.227.g00780c9af4-goog ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-27 8:35 ` [PATCH 2/2] drivers/misc: add transfer ioctl " Sami Kyöstilä @ 2022-01-27 9:41 ` Greg KH 2022-01-28 7:42 ` Sami Kyostila 2022-01-27 22:39 ` Randy Dunlap 1 sibling, 1 reply; 15+ messages in thread From: Greg KH @ 2022-01-27 9:41 UTC (permalink / raw) To: Sami Kyöstilä; +Cc: LKML, dtor, evanbenn, arnd On Thu, Jan 27, 2022 at 07:35:45PM +1100, Sami Kyöstilä wrote: > This patch adds an ioctl operation for sending and receiving data from > the ChromeOS snooping protection sensor (a.k.a., HPS). This allows > userspace programs to perform a combined read/write I2C transaction > through a single syscall. > > The I2C wire protocol for the device is documented at: > > https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ > refs/heads/main/docs/host_device_i2c_protocol.md > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > --- > > MAINTAINERS | 1 + > drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ > include/uapi/linux/hps.h | 20 ++++++++++ > 3 files changed, 102 insertions(+) > create mode 100644 include/uapi/linux/hps.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index 9dea4b8c2ab5..d5fc066fdbc2 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -8803,6 +8803,7 @@ M: Sami Kyöstilä <skyostil@chromium.org> > R: Evan Benn <evanbenn@chromium.org> > S: Maintained > F: drivers/misc/hps-i2c.c > +F: include/uapi/linux/hps.h > > HSI SUBSYSTEM > M: Sebastian Reichel <sre@kernel.org> > diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c > index fe9f073b0352..748ead49d678 100644 > --- a/drivers/misc/hps-i2c.c > +++ b/drivers/misc/hps-i2c.c > @@ -17,9 +17,11 @@ > #include <linux/i2c.h> > #include <linux/module.h> > #include <linux/pm_runtime.h> > +#include <uapi/linux/hps.h> > > #define HPS_ACPI_ID "GOOG0020" > #define HPS_MAX_DEVICES 1 > +#define HPS_MAX_MSG_SIZE 8192 > > struct hps_drvdata { > struct i2c_client *client; > @@ -60,6 +62,8 @@ static int hps_open(struct inode *inode, struct file *file) > ret = pm_runtime_get_sync(dev); > if (ret < 0) > goto pm_get_fail; > + > + file->private_data = hps->client; > return 0; > > pm_get_fail: > @@ -84,10 +88,87 @@ static int hps_release(struct inode *inode, struct file *file) > return ret; > } > > +static int hps_do_ioctl_transfer(struct i2c_client *client, > + struct hps_transfer_ioctl_data *args) > +{ > + int ret; > + int nmsg = 0; > + struct i2c_msg msgs[2] = { > + { > + .addr = client->addr, > + .flags = client->flags, > + }, > + { > + .addr = client->addr, > + .flags = client->flags, > + }, > + }; > + > + if (args->isize) { > + msgs[nmsg].len = args->isize; > + msgs[nmsg].buf = memdup_user(args->ibuf, args->isize); > + if (IS_ERR(msgs[nmsg].buf)) { > + ret = PTR_ERR(msgs[nmsg].buf); > + goto memdup_fail; > + } > + nmsg++; > + } > + > + if (args->osize) { > + msgs[nmsg].len = args->osize; > + msgs[nmsg].buf = memdup_user(args->obuf, args->osize); > + msgs[nmsg].flags |= I2C_M_RD; > + if (IS_ERR(msgs[nmsg].buf)) { > + ret = PTR_ERR(msgs[nmsg].buf); > + goto memdup_fail; > + } > + nmsg++; > + } > + > + ret = i2c_transfer(client->adapter, &msgs[0], nmsg); > + if (ret > 0 && args->osize) { > + if (copy_to_user(args->obuf, msgs[nmsg - 1].buf, ret)) > + ret = -EFAULT; > + } Why can't you just do normal i2c transfers to/from userspace instead of requring a custom ioctl? thanks, greg k-h ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-27 9:41 ` Greg KH @ 2022-01-28 7:42 ` Sami Kyostila 2022-01-28 9:36 ` Greg KH 2022-01-28 9:47 ` Arnd Bergmann 0 siblings, 2 replies; 15+ messages in thread From: Sami Kyostila @ 2022-01-28 7:42 UTC (permalink / raw) To: Greg KH; +Cc: LKML, dtor, evanbenn, arnd to 27. tammik. 2022 klo 20.41 Greg KH (gregkh@linuxfoundation.org) kirjoitti: > > On Thu, Jan 27, 2022 at 07:35:45PM +1100, Sami Kyöstilä wrote: > > This patch adds an ioctl operation for sending and receiving data from > > the ChromeOS snooping protection sensor (a.k.a., HPS). This allows > > userspace programs to perform a combined read/write I2C transaction > > through a single syscall. > > > > The I2C wire protocol for the device is documented at: > > > > https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ > > refs/heads/main/docs/host_device_i2c_protocol.md > > > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > > --- > > > > MAINTAINERS | 1 + > > drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ > > include/uapi/linux/hps.h | 20 ++++++++++ > > 3 files changed, 102 insertions(+) > > create mode 100644 include/uapi/linux/hps.h > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index 9dea4b8c2ab5..d5fc066fdbc2 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -8803,6 +8803,7 @@ M: Sami Kyöstilä <skyostil@chromium.org> > > R: Evan Benn <evanbenn@chromium.org> > > S: Maintained > > F: drivers/misc/hps-i2c.c > > +F: include/uapi/linux/hps.h > > > > HSI SUBSYSTEM > > M: Sebastian Reichel <sre@kernel.org> > > diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c > > index fe9f073b0352..748ead49d678 100644 > > --- a/drivers/misc/hps-i2c.c > > +++ b/drivers/misc/hps-i2c.c > > @@ -17,9 +17,11 @@ > > #include <linux/i2c.h> > > #include <linux/module.h> > > #include <linux/pm_runtime.h> > > +#include <uapi/linux/hps.h> > > > > #define HPS_ACPI_ID "GOOG0020" > > #define HPS_MAX_DEVICES 1 > > +#define HPS_MAX_MSG_SIZE 8192 > > > > struct hps_drvdata { > > struct i2c_client *client; > > @@ -60,6 +62,8 @@ static int hps_open(struct inode *inode, struct file *file) > > ret = pm_runtime_get_sync(dev); > > if (ret < 0) > > goto pm_get_fail; > > + > > + file->private_data = hps->client; > > return 0; > > > > pm_get_fail: > > @@ -84,10 +88,87 @@ static int hps_release(struct inode *inode, struct file *file) > > return ret; > > } > > > > +static int hps_do_ioctl_transfer(struct i2c_client *client, > > + struct hps_transfer_ioctl_data *args) > > +{ > > + int ret; > > + int nmsg = 0; > > + struct i2c_msg msgs[2] = { > > + { > > + .addr = client->addr, > > + .flags = client->flags, > > + }, > > + { > > + .addr = client->addr, > > + .flags = client->flags, > > + }, > > + }; > > + > > + if (args->isize) { > > + msgs[nmsg].len = args->isize; > > + msgs[nmsg].buf = memdup_user(args->ibuf, args->isize); > > + if (IS_ERR(msgs[nmsg].buf)) { > > + ret = PTR_ERR(msgs[nmsg].buf); > > + goto memdup_fail; > > + } > > + nmsg++; > > + } > > + > > + if (args->osize) { > > + msgs[nmsg].len = args->osize; > > + msgs[nmsg].buf = memdup_user(args->obuf, args->osize); > > + msgs[nmsg].flags |= I2C_M_RD; > > + if (IS_ERR(msgs[nmsg].buf)) { > > + ret = PTR_ERR(msgs[nmsg].buf); > > + goto memdup_fail; > > + } > > + nmsg++; > > + } > > + > > + ret = i2c_transfer(client->adapter, &msgs[0], nmsg); > > + if (ret > 0 && args->osize) { > > + if (copy_to_user(args->obuf, msgs[nmsg - 1].buf, ret)) > > + ret = -EFAULT; > > + } > > Why can't you just do normal i2c transfers to/from userspace instead of > requring a custom ioctl? The main reason is security: without this driver, in order to talk to HPS the userspace daemon needs read/write access to the entire I2C controller (e.g., /dev/i2c-0). This means the daemon can also control any other I2C device which happens to be on the same bus. With a separate ioctl we can limit access to just HPS. As far as I can tell, there's no way to restrict access on a per-device level with normal i2c, but I'd be happy to be proven wrong :) > > thanks, > > greg k-h - Sami ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-28 7:42 ` Sami Kyostila @ 2022-01-28 9:36 ` Greg KH 2022-01-31 8:23 ` Sami Kyostila 2022-01-28 9:47 ` Arnd Bergmann 1 sibling, 1 reply; 15+ messages in thread From: Greg KH @ 2022-01-28 9:36 UTC (permalink / raw) To: Sami Kyostila; +Cc: LKML, dtor, evanbenn, arnd On Fri, Jan 28, 2022 at 06:42:08PM +1100, Sami Kyostila wrote: > to 27. tammik. 2022 klo 20.41 Greg KH (gregkh@linuxfoundation.org) kirjoitti: > > > > On Thu, Jan 27, 2022 at 07:35:45PM +1100, Sami Kyöstilä wrote: > > > This patch adds an ioctl operation for sending and receiving data from > > > the ChromeOS snooping protection sensor (a.k.a., HPS). This allows > > > userspace programs to perform a combined read/write I2C transaction > > > through a single syscall. > > > > > > The I2C wire protocol for the device is documented at: > > > > > > https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ > > > refs/heads/main/docs/host_device_i2c_protocol.md > > > > > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > > > --- > > > > > > MAINTAINERS | 1 + > > > drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ > > > include/uapi/linux/hps.h | 20 ++++++++++ > > > 3 files changed, 102 insertions(+) > > > create mode 100644 include/uapi/linux/hps.h > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > > index 9dea4b8c2ab5..d5fc066fdbc2 100644 > > > --- a/MAINTAINERS > > > +++ b/MAINTAINERS > > > @@ -8803,6 +8803,7 @@ M: Sami Kyöstilä <skyostil@chromium.org> > > > R: Evan Benn <evanbenn@chromium.org> > > > S: Maintained > > > F: drivers/misc/hps-i2c.c > > > +F: include/uapi/linux/hps.h > > > > > > HSI SUBSYSTEM > > > M: Sebastian Reichel <sre@kernel.org> > > > diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c > > > index fe9f073b0352..748ead49d678 100644 > > > --- a/drivers/misc/hps-i2c.c > > > +++ b/drivers/misc/hps-i2c.c > > > @@ -17,9 +17,11 @@ > > > #include <linux/i2c.h> > > > #include <linux/module.h> > > > #include <linux/pm_runtime.h> > > > +#include <uapi/linux/hps.h> > > > > > > #define HPS_ACPI_ID "GOOG0020" > > > #define HPS_MAX_DEVICES 1 > > > +#define HPS_MAX_MSG_SIZE 8192 > > > > > > struct hps_drvdata { > > > struct i2c_client *client; > > > @@ -60,6 +62,8 @@ static int hps_open(struct inode *inode, struct file *file) > > > ret = pm_runtime_get_sync(dev); > > > if (ret < 0) > > > goto pm_get_fail; > > > + > > > + file->private_data = hps->client; > > > return 0; > > > > > > pm_get_fail: > > > @@ -84,10 +88,87 @@ static int hps_release(struct inode *inode, struct file *file) > > > return ret; > > > } > > > > > > +static int hps_do_ioctl_transfer(struct i2c_client *client, > > > + struct hps_transfer_ioctl_data *args) > > > +{ > > > + int ret; > > > + int nmsg = 0; > > > + struct i2c_msg msgs[2] = { > > > + { > > > + .addr = client->addr, > > > + .flags = client->flags, > > > + }, > > > + { > > > + .addr = client->addr, > > > + .flags = client->flags, > > > + }, > > > + }; > > > + > > > + if (args->isize) { > > > + msgs[nmsg].len = args->isize; > > > + msgs[nmsg].buf = memdup_user(args->ibuf, args->isize); > > > + if (IS_ERR(msgs[nmsg].buf)) { > > > + ret = PTR_ERR(msgs[nmsg].buf); > > > + goto memdup_fail; > > > + } > > > + nmsg++; > > > + } > > > + > > > + if (args->osize) { > > > + msgs[nmsg].len = args->osize; > > > + msgs[nmsg].buf = memdup_user(args->obuf, args->osize); > > > + msgs[nmsg].flags |= I2C_M_RD; > > > + if (IS_ERR(msgs[nmsg].buf)) { > > > + ret = PTR_ERR(msgs[nmsg].buf); > > > + goto memdup_fail; > > > + } > > > + nmsg++; > > > + } > > > + > > > + ret = i2c_transfer(client->adapter, &msgs[0], nmsg); > > > + if (ret > 0 && args->osize) { > > > + if (copy_to_user(args->obuf, msgs[nmsg - 1].buf, ret)) > > > + ret = -EFAULT; > > > + } > > > > Why can't you just do normal i2c transfers to/from userspace instead of > > requring a custom ioctl? > > The main reason is security: without this driver, in order to talk to > HPS the userspace daemon needs read/write access to the entire I2C > controller (e.g., /dev/i2c-0). This means the daemon can also control > any other I2C device which happens to be on the same bus. With a > separate ioctl we can limit access to just HPS. Then use seccomp for this? > As far as I can tell, there's no way to restrict access on a > per-device level with normal i2c, but I'd be happy to be proven wrong > :) Selinux rules? What else is on this bus for the device that you care about? thanks, greg k-h ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-28 9:36 ` Greg KH @ 2022-01-31 8:23 ` Sami Kyostila 2022-01-31 12:51 ` Arnd Bergmann 0 siblings, 1 reply; 15+ messages in thread From: Sami Kyostila @ 2022-01-31 8:23 UTC (permalink / raw) To: Greg KH; +Cc: LKML, dtor, evanbenn, arnd pe 28. tammik. 2022 klo 20.36 Greg KH (gregkh@linuxfoundation.org) kirjoitti: > > On Fri, Jan 28, 2022 at 06:42:08PM +1100, Sami Kyostila wrote: > > to 27. tammik. 2022 klo 20.41 Greg KH (gregkh@linuxfoundation.org) kirjoitti: > > > > > > On Thu, Jan 27, 2022 at 07:35:45PM +1100, Sami Kyöstilä wrote: > > > > This patch adds an ioctl operation for sending and receiving data from > > > > the ChromeOS snooping protection sensor (a.k.a., HPS). This allows > > > > userspace programs to perform a combined read/write I2C transaction > > > > through a single syscall. > > > > > > > > The I2C wire protocol for the device is documented at: > > > > > > > > https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ > > > > refs/heads/main/docs/host_device_i2c_protocol.md > > > > > > > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > > > > --- > > > > > > > > MAINTAINERS | 1 + > > > > drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ > > > > include/uapi/linux/hps.h | 20 ++++++++++ > > > > 3 files changed, 102 insertions(+) > > > > create mode 100644 include/uapi/linux/hps.h > > > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > > > index 9dea4b8c2ab5..d5fc066fdbc2 100644 > > > > --- a/MAINTAINERS > > > > +++ b/MAINTAINERS > > > > @@ -8803,6 +8803,7 @@ M: Sami Kyöstilä <skyostil@chromium.org> > > > > R: Evan Benn <evanbenn@chromium.org> > > > > S: Maintained > > > > F: drivers/misc/hps-i2c.c > > > > +F: include/uapi/linux/hps.h > > > > > > > > HSI SUBSYSTEM > > > > M: Sebastian Reichel <sre@kernel.org> > > > > diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c > > > > index fe9f073b0352..748ead49d678 100644 > > > > --- a/drivers/misc/hps-i2c.c > > > > +++ b/drivers/misc/hps-i2c.c > > > > @@ -17,9 +17,11 @@ > > > > #include <linux/i2c.h> > > > > #include <linux/module.h> > > > > #include <linux/pm_runtime.h> > > > > +#include <uapi/linux/hps.h> > > > > > > > > #define HPS_ACPI_ID "GOOG0020" > > > > #define HPS_MAX_DEVICES 1 > > > > +#define HPS_MAX_MSG_SIZE 8192 > > > > > > > > struct hps_drvdata { > > > > struct i2c_client *client; > > > > @@ -60,6 +62,8 @@ static int hps_open(struct inode *inode, struct file *file) > > > > ret = pm_runtime_get_sync(dev); > > > > if (ret < 0) > > > > goto pm_get_fail; > > > > + > > > > + file->private_data = hps->client; > > > > return 0; > > > > > > > > pm_get_fail: > > > > @@ -84,10 +88,87 @@ static int hps_release(struct inode *inode, struct file *file) > > > > return ret; > > > > } > > > > > > > > +static int hps_do_ioctl_transfer(struct i2c_client *client, > > > > + struct hps_transfer_ioctl_data *args) > > > > +{ > > > > + int ret; > > > > + int nmsg = 0; > > > > + struct i2c_msg msgs[2] = { > > > > + { > > > > + .addr = client->addr, > > > > + .flags = client->flags, > > > > + }, > > > > + { > > > > + .addr = client->addr, > > > > + .flags = client->flags, > > > > + }, > > > > + }; > > > > + > > > > + if (args->isize) { > > > > + msgs[nmsg].len = args->isize; > > > > + msgs[nmsg].buf = memdup_user(args->ibuf, args->isize); > > > > + if (IS_ERR(msgs[nmsg].buf)) { > > > > + ret = PTR_ERR(msgs[nmsg].buf); > > > > + goto memdup_fail; > > > > + } > > > > + nmsg++; > > > > + } > > > > + > > > > + if (args->osize) { > > > > + msgs[nmsg].len = args->osize; > > > > + msgs[nmsg].buf = memdup_user(args->obuf, args->osize); > > > > + msgs[nmsg].flags |= I2C_M_RD; > > > > + if (IS_ERR(msgs[nmsg].buf)) { > > > > + ret = PTR_ERR(msgs[nmsg].buf); > > > > + goto memdup_fail; > > > > + } > > > > + nmsg++; > > > > + } > > > > + > > > > + ret = i2c_transfer(client->adapter, &msgs[0], nmsg); > > > > + if (ret > 0 && args->osize) { > > > > + if (copy_to_user(args->obuf, msgs[nmsg - 1].buf, ret)) > > > > + ret = -EFAULT; > > > > + } > > > > > > Why can't you just do normal i2c transfers to/from userspace instead of > > > requring a custom ioctl? > > > > The main reason is security: without this driver, in order to talk to > > HPS the userspace daemon needs read/write access to the entire I2C > > controller (e.g., /dev/i2c-0). This means the daemon can also control > > any other I2C device which happens to be on the same bus. With a > > separate ioctl we can limit access to just HP > Then use seccomp for this? As far as I can tell, seccomp can't do this because it can't read the device address field[1] which is behind two userspace pointer hops in the I2C_RDWR ioctl[2]. [1] https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/i2c.h#L74 [2] https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/i2c-dev.h#L51 > > > As far as I can tell, there's no way to restrict access on a > > per-device level with normal i2c, but I'd be happy to be proven wrong > > :) > > Selinux rules? I guess we could add an LSM hook for I2C transfers, but that would require baking device addresses into the SELinux policy which seems a little unfortunate. I think that leaves the options suggested by Arnd (thanks!): a) Add a generic way to expose device nodes for individual I2C devices (something like /dev/i2c/by-id/NN?). b) Make the ioctl interface more fully featured instead of just exposing I2C. I think I'm leaning toward (a) since it's not yet totally clear what the right high level abstraction for this type of device is (e.g., should it be HID, in which case the protocol should probably become HID-I2C). If this sounds okay, then I suggest we merge just the power control patch from this series (with comments addressed) and I'll follow-up with splitting out the i2c devices. > What else is on this bus for the device that you care about? That's really up to the device manufacturer; it could be anything from touchpads to cameras or fingerprint scanners. > thanks, > > greg k-h - Sami ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-31 8:23 ` Sami Kyostila @ 2022-01-31 12:51 ` Arnd Bergmann 0 siblings, 0 replies; 15+ messages in thread From: Arnd Bergmann @ 2022-01-31 12:51 UTC (permalink / raw) To: Sami Kyostila Cc: Greg KH, LKML, Dmitry Torokhov, evanbenn, Arnd Bergmann, Linux I2C, Wolfram Sang On Mon, Jan 31, 2022 at 9:23 AM Sami Kyostila <skyostil@chromium.org> wrote: > > I guess we could add an LSM hook for I2C transfers, but that would > require baking device addresses into the SELinux policy which seems a > little unfortunate. > > I think that leaves the options suggested by Arnd (thanks!): > > a) Add a generic way to expose device nodes for individual I2C devices > (something like /dev/i2c/by-id/NN?). > > b) Make the ioctl interface more fully featured instead of just exposing I2C. > > I think I'm leaning toward (a) since it's not yet totally clear what > the right high level abstraction for this type of device is (e.g., > should it be HID, in which case the protocol should probably become > HID-I2C). (adding i2c list to cc) I think the implementation of the character device should be really straightforward, it can probably just use the exact same ioctls as the normal device, or a subset of them, and filter out any access that has the wrong address with ioctl(fd, I2C_SLAVE, ...) or other commands. The tricky part is coming up with a sensible way of creating those character device nodes, as there generic method of knowing what is attached to the bus. I suppose this could be done either automatically based on the nodes in DT, or it could be done with user interaction like a new ioctl command on the normal device node or some sysfs interface to create the chardev for a particular slave device. Arnd ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-28 7:42 ` Sami Kyostila 2022-01-28 9:36 ` Greg KH @ 2022-01-28 9:47 ` Arnd Bergmann 1 sibling, 0 replies; 15+ messages in thread From: Arnd Bergmann @ 2022-01-28 9:47 UTC (permalink / raw) To: Sami Kyostila; +Cc: Greg KH, LKML, Dmitry Torokhov, evanbenn, Arnd Bergmann On Fri, Jan 28, 2022 at 8:42 AM Sami Kyostila <skyostil@chromium.org> wrote: > to 27. tammik. 2022 klo 20.41 Greg KH (gregkh@linuxfoundation.org) kirjoitti: > > > > Why can't you just do normal i2c transfers to/from userspace instead of > > requring a custom ioctl? > > The main reason is security: without this driver, in order to talk to > HPS the userspace daemon needs read/write access to the entire I2C > controller (e.g., /dev/i2c-0). This means the daemon can also control > any other I2C device which happens to be on the same bus. With a > separate ioctl we can limit access to just HPS. > > As far as I can tell, there's no way to restrict access on a > per-device level with normal i2c, but I'd be happy to be proven wrong > :) I don't know if is correct, but I trust your research on that. However, I would still argue that instead of adding a custom low-level interface to give user access to a single raw i2c device, we would be better off doing one of two other approaches: a) add the generic interface you are missing -- it seems unlikely that you are the only user that has come across this issue, and adding a generic per-device interface to complement the per-controller one would likely help avoid others coming up with the same thing elsewhere, using yet another set of custom ioctls. b) move part of your application into the kernel, and provide a high-level abstraction for your device in place of the low-level i2c access. Arnd ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-27 8:35 ` [PATCH 2/2] drivers/misc: add transfer ioctl " Sami Kyöstilä 2022-01-27 9:41 ` Greg KH @ 2022-01-27 22:39 ` Randy Dunlap 2022-01-28 7:42 ` Sami Kyostila 1 sibling, 1 reply; 15+ messages in thread From: Randy Dunlap @ 2022-01-27 22:39 UTC (permalink / raw) To: Sami Kyöstilä, LKML; +Cc: dtor, evanbenn, arnd, gregkh On 1/27/22 00:35, Sami Kyöstilä wrote: > This patch adds an ioctl operation for sending and receiving data from > the ChromeOS snooping protection sensor (a.k.a., HPS). This allows > userspace programs to perform a combined read/write I2C transaction > through a single syscall. > > The I2C wire protocol for the device is documented at: > > https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ > refs/heads/main/docs/host_device_i2c_protocol.md > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > --- > > MAINTAINERS | 1 + > drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ > include/uapi/linux/hps.h | 20 ++++++++++ > 3 files changed, 102 insertions(+) > create mode 100644 include/uapi/linux/hps.h > Hi-- If your next patch version continues to use an ioctl, its magic "number" ('h') should be documented in Documentation/userspace-api/ioctl/ioctl-number.rst. thanks. > diff --git a/include/uapi/linux/hps.h b/include/uapi/linux/hps.h > new file mode 100644 > index 000000000000..2c1bd174cd02 > --- /dev/null > +++ b/include/uapi/linux/hps.h > @@ -0,0 +1,20 @@ > +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ > +/* > + * Copyright 2022 Google LLC. > + */ > + > +#ifndef _UAPI_HPS_H > +#define _UAPI_HPS_H > + > +#include <linux/types.h> > + > +#define HPS_IOC_TRANSFER _IOWR('h', 0x01, struct hps_transfer_ioctl_data) > + > +struct hps_transfer_ioctl_data { > + __u32 isize; /* Number of bytes to send */ > + unsigned char __user *ibuf; /* Input buffer */ > + __u32 osize; /* Number of bytes to receive */ > + unsigned char __user *obuf; /* Output buffer */ > +}; > + > +#endif /* _UAPI_HPS_H */ -- ~Randy ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS 2022-01-27 22:39 ` Randy Dunlap @ 2022-01-28 7:42 ` Sami Kyostila 0 siblings, 0 replies; 15+ messages in thread From: Sami Kyostila @ 2022-01-28 7:42 UTC (permalink / raw) To: Randy Dunlap; +Cc: LKML, dtor, evanbenn, arnd, gregkh pe 28. tammik. 2022 klo 9.39 Randy Dunlap (rdunlap@infradead.org) kirjoitti: > > > > On 1/27/22 00:35, Sami Kyöstilä wrote: > > This patch adds an ioctl operation for sending and receiving data from > > the ChromeOS snooping protection sensor (a.k.a., HPS). This allows > > userspace programs to perform a combined read/write I2C transaction > > through a single syscall. > > > > The I2C wire protocol for the device is documented at: > > > > https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ > > refs/heads/main/docs/host_device_i2c_protocol.md > > > > Signed-off-by: Sami Kyöstilä <skyostil@chromium.org> > > --- > > > > MAINTAINERS | 1 + > > drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ > > include/uapi/linux/hps.h | 20 ++++++++++ > > 3 files changed, 102 insertions(+) > > create mode 100644 include/uapi/linux/hps.h > > > > Hi-- > > If your next patch version continues to use an ioctl, its magic "number" > ('h') should be documented in Documentation/userspace-api/ioctl/ioctl-number.rst. Ah, thanks for the pointer. Will do. - Sami > > thanks. > > > diff --git a/include/uapi/linux/hps.h b/include/uapi/linux/hps.h > > new file mode 100644 > > index 000000000000..2c1bd174cd02 > > --- /dev/null > > +++ b/include/uapi/linux/hps.h > > @@ -0,0 +1,20 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ > > +/* > > + * Copyright 2022 Google LLC. > > + */ > > + > > +#ifndef _UAPI_HPS_H > > +#define _UAPI_HPS_H > > + > > +#include <linux/types.h> > > + > > +#define HPS_IOC_TRANSFER _IOWR('h', 0x01, struct hps_transfer_ioctl_data) > > + > > +struct hps_transfer_ioctl_data { > > + __u32 isize; /* Number of bytes to send */ > > + unsigned char __user *ibuf; /* Input buffer */ > > + __u32 osize; /* Number of bytes to receive */ > > + unsigned char __user *obuf; /* Output buffer */ > > +}; > > + > > +#endif /* _UAPI_HPS_H */ > > -- > ~Randy ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2022-02-18 17:20 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-01-27 8:35 [PATCH 0/2] Add a driver for the ChromeOS snooping protection sensor (HPS) Sami Kyöstilä 2022-01-27 8:35 ` [PATCH 1/2] drivers/misc: add a driver for HPS Sami Kyöstilä 2022-01-27 9:40 ` Greg KH 2022-01-28 7:41 ` Sami Kyostila 2022-01-28 9:36 ` Greg KH 2022-02-18 17:20 ` Pavel Machek 2022-01-27 8:35 ` [PATCH 2/2] drivers/misc: add transfer ioctl " Sami Kyöstilä 2022-01-27 9:41 ` Greg KH 2022-01-28 7:42 ` Sami Kyostila 2022-01-28 9:36 ` Greg KH 2022-01-31 8:23 ` Sami Kyostila 2022-01-31 12:51 ` Arnd Bergmann 2022-01-28 9:47 ` Arnd Bergmann 2022-01-27 22:39 ` Randy Dunlap 2022-01-28 7:42 ` Sami Kyostila
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.