Re: [PATCH 4/4] Add MMC Password Protection (lock/unlock) supportV9: mmc_sysfs.diff

From: Anderson Briglia
Date: Mon Feb 05 2007 - 16:28:56 EST


Hi Pierre,

ext Pierre Ossman wrote:
> Anderson Briglia wrote:
>> Hi Pierre,
>>
>> How about now? Is better?
>>
>>
>
> Locking problem is still there. You need to unclaim the host even when
> claim fails.

Bug fixed. Is there anything else to improve?

Regards,

Anderson Briglia
Implement MMC password force erase, remove password, change password,
unlock card and assign password operations. It uses the sysfs mechanism
to send commands to the MMC subsystem.

Signed-off-by: Carlos Eduardo Aguiar <carlos.aguiar@xxxxxxxxxxx>
Signed-off-by: Anderson Lizardo <anderson.lizardo@xxxxxxxxxxx>
Signed-off-by: Anderson Briglia <anderson.briglia@xxxxxxxxxxx>

Index: linux-linus-2.6/drivers/mmc/mmc_sysfs.c
===================================================================
--- linux-linus-2.6.orig/drivers/mmc/mmc_sysfs.c 2007-02-05 17:32:05.000000000 -0400
+++ linux-linus-2.6/drivers/mmc/mmc_sysfs.c 2007-02-05 17:32:19.000000000 -0400
@@ -17,6 +17,7 @@
#include <linux/idr.h>
#include <linux/workqueue.h>
#include <linux/key.h>
+#include <linux/err.h>

#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -65,6 +66,102 @@ static struct device_attribute mmc_dev_a

static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);

+#ifdef CONFIG_MMC_PASSWORDS
+
+static ssize_t
+mmc_lockable_show(struct device *dev, struct device_attribute *att, char *buf)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ if (!mmc_card_lockable(card))
+ return sprintf(buf, "unsupported\n");
+ else
+ return sprintf(buf, "%slocked\n", mmc_card_locked(card) ?
+ "" : "un");
+}
+
+/*
+ * implement MMC password functions: force erase, remove password, change
+ * password, unlock card and assign password.
+ */
+static ssize_t
+mmc_lockable_store(struct device *dev, struct device_attribute *att,
+ const char *data, size_t len)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+ int ret;
+
+ if(!mmc_card_lockable(card))
+ return -EINVAL;
+
+ ret = mmc_card_claim_host(card);
+ if (ret != MMC_ERR_NONE) {
+ mmc_card_release_host(card);
+ return -EINVAL;
+ }
+
+ ret = -EINVAL;
+ if (mmc_card_locked(card) && !strncmp(data, "erase", 5)) {
+ /* forced erase only works while card is locked */
+ mmc_lock_unlock(card, NULL, MMC_LOCK_MODE_ERASE);
+ ret = len;
+ } else if (!mmc_card_locked(card) && !strncmp(data, "remove", 6)) {
+ /* remove password only works while card is unlocked */
+ struct key *mmc_key = request_key(&mmc_key_type, "mmc:key", "remove");
+
+ if (!IS_ERR(mmc_key)) {
+ ret = mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_CLR_PWD);
+ if (!ret)
+ ret = len;
+ } else
+ dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
+ } else if (!mmc_card_locked(card) && ((!strncmp(data, "assign", 6)) ||
+ (!strncmp(data, "change", 6)))) {
+ /* assign or change */
+ struct key *mmc_key;
+
+ if(!(strncmp(data, "assign", 6)))
+ mmc_key = request_key(&mmc_key_type, "mmc:key", "assign");
+ else
+ mmc_key = request_key(&mmc_key_type, "mmc:key", "change");
+
+ if (!IS_ERR(mmc_key)) {
+ ret = mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_SET_PWD);
+ if (!ret)
+ ret = len;
+ } else
+ dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
+ } else if (mmc_card_locked(card) && !strncmp(data, "unlock", 6)) {
+ /* unlock */
+ struct key *mmc_key = request_key(&mmc_key_type, "mmc:key", "unlock");
+ if (!IS_ERR(mmc_key)) {
+ ret = mmc_lock_unlock(card, mmc_key, MMC_LOCK_MODE_UNLOCK);
+ if (ret) {
+ dev_dbg(&card->dev, "Wrong password\n");
+ ret = -EINVAL;
+ }
+ else {
+ mmc_card_release_host(card);
+ device_release_driver(dev);
+ ret = device_attach(dev);
+ if(!ret)
+ return -EINVAL;
+ else
+ return len;
+ }
+ } else
+ dev_dbg(&card->dev, "request_key returned error %ld\n", PTR_ERR(mmc_key));
+ }
+
+ mmc_card_release_host(card);
+ return ret;
+}
+
+static struct device_attribute mmc_dev_attr_lockable =
+ __ATTR(lockable, S_IWUSR | S_IRUGO,
+ mmc_lockable_show, mmc_lockable_store);
+
+#endif

static void mmc_release_card(struct device *dev)
{
@@ -234,6 +331,11 @@ int mmc_register_card(struct mmc_card *c
if (ret)
device_del(&card->dev);
}
+#ifdef CONFIG_MMC_PASSWORDS
+ ret = device_create_file(&card->dev, &mmc_dev_attr_lockable);
+ if (ret)
+ device_del(&card->dev);
+#endif
}
return ret;
}
@@ -248,6 +350,9 @@ void mmc_remove_card(struct mmc_card *ca
if (mmc_card_sd(card))
device_remove_file(&card->dev, &mmc_dev_attr_scr);

+#ifdef CONFIG_MMC_PASSWORDS
+ device_remove_file(&card->dev, &mmc_dev_attr_lockable);
+#endif
device_del(&card->dev);
}