Add MMC password protection (lock/unlock) support V3
PATCH 4/5 Add MMC password protection (lock/unlock) support V3
Implement MMC password reset and forced erase support. It uses the sysfs mechanism to send commands to the MMC subsystem. Usage:
Forced erase:
echo erase > /sys/bus/mmc/devices/mmc0\:0001/lockable
Remove password:
echo remove > /sys/bus/mmc/devices/mmc0\:0001/lockable
drivers/mmc/mmc_sysfs.c +81 -7
@@ -16,6 +16,7 @@#include <linux/device.h> #include <linux/idr.h> #include <linux/key.h> +#include <linux/err.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h>
@@ -26,6 +27,10 @@#define KEY_OP_INSTANTIATE 1#define KEY_OP_UPDATE 2 +#ifdef CONFIG_MMC_DEBUG +#define DEBUG /* for dev_dbg(), pr_debug(), etc */ +#endif +#define dev_to_mmc_card (d) container_of(d, struct mmc_card, dev)#define to_mmc_driver (d) container_of(d, struct mmc_driver, drv)#define cls_dev_to_mmc_host (d) container_of(d, struct mmc_host, class_dev)
@@ -67,6 +72,58 @@ static struct device_attribute mmc_dev_astatic 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,"unlockable\n" ); +else +return sprintf (buf,"lockable, %slocked\n" ,mmc_card_locked (card) ? +"" :"un" ); +} + +/* +* implement MMC password reset ("remove password") and forced erase ("forgot +* 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); + +if (!mmc_card_lockable (card)) +return -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 ); +return 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" ,NULL ); + +if (!IS_ERR (mmc_key)) { +int err =mmc_lock_unlock (card, mmc_key,MMC_LOCK_MODE_CLR_PWD ); +if (!err) +return len; + }else +dev_dbg (&card->dev,"request_key returned error %ld\n" ,PTR_ERR (mmc_key)); + } + +return -EINVAL ; +} + +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) {
@@ -238,6 +295,11 @@ int mmc_register_card(struct mmc_card *cif (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; }
@@ -251,7 +313,9 @@ void mmc_remove_card(struct mmc_card *caif (mmc_card_present (card)) {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); }
@@ -305,19 +369,25 @@ static int manage_key(struct key *key, c zap =NULL ; ret = -EINVAL ; -if (datalen <=0 || datalen >MMC_KEYLEN_MAXBYTES || !data) +if (datalen <=0 || datalen >MMC_KEYLEN_MAXBYTES || !data){ +dev_dbg (&card->dev,"Invalid data\n" ); goto error; + }if (operation ==KEY_OP_INSTANTIATE ) {/* KEY_OP_INSTANTIATE */ ret =key_payload_reserve (key, datalen); -if (ret <0 ) - goto error; +if (ret <0 ){ +dev_dbg (&card->dev,"ret = %d" , ret); + goto error; + } } ret = -ENOMEM ; mpayload =kmalloc (sizeof (*mpayload) + datalen,GFP_KERNEL ); -if (!mpayload) +if (!mpayload){ +dev_dbg (&card->dev,"Unable to allocate mpayload structure\n" ); goto error; + } mpayload->datalen = datalen;memcpy (mpayload->data, data, datalen);
@@ -341,8 +411,10 @@ static int manage_key(struct key *key, c ret = -EINVAL ; dev =bus_find_device (&mmc_bus_type,NULL ,NULL , mmc_match_lockable); -if (!dev) +if (!dev){ +dev_dbg (&card->dev,"Unable to locate device\n" ); goto error; + } card =dev_to_mmc_card (dev);if (operation ==KEY_OP_INSTANTIATE ) {/* KEY_OP_INSTANTIATE */
@@ -359,8 +431,10 @@ static int manage_key(struct key *key, c ret =mmc_lock_unlock (card, key,MMC_LOCK_MODE_SET_PWD ); } -if (ret) +if (ret){ ret = -EKEYREJECTED ; +dev_dbg (&card->dev,"Key was rejected\n" ); + }if (operation ==KEY_OP_UPDATE )/* KEY_OP_UPDATE */ call_rcu (&zap->rcu, mmc_key_update_rcu_disposal);
Quoted 4 lines · Anderson Briglia
drivers/mmc/mmc_sysfs.c +0
-0@@ -238,6 +295,11 @@ int mmc_register_card(struct mmc_card *cif (ret)
drivers/mmc/mmc_sysfs.c int mmc_register_card(struct mmc_card *c · line 305
Quoted 10 lines
drivers/mmc/mmc_sysfs.c +5
-0device_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; }
It might be wise to also check the command classes here. I don't believe SDIO supports locking.
Rgds
Pierre
Quoted 13 lines · Pierre Ossman
Quoted 10 lines · Anderson Briglia
drivers/mmc/mmc_sysfs.c +5
-0@@ -238,6 +295,11 @@ int mmc_register_card(struct mmc_card *cif (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 }
Quoted 8 lines
drivers/mmc/mmc_sysfs.c int mmc_register_card(struct mmc_card *c · line 305
Quoted 4 lines
drivers/mmc/mmc_sysfs.c +0
-0return ret; }It might be wise to also check the command classes here. I don't believe SDIO supports locking.
In this case, the lockable attribute will show "unlockable", which is the expected behavior. The lockable attribute will always be present, the card being lockable or not.
Regards,
Anderson Briglia
INdT - Manaus
Quoted 23 lines · Anderson Briglia
Quoted 13 lines · Pierre Ossman
Quoted 10 lines · Anderson Briglia
drivers/mmc/mmc_sysfs.c +5
-0@@ -238,6 +295,11 @@ int mmc_register_card(struct mmc_card *cif (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 }Quoted 8 lines
drivers/mmc/mmc_sysfs.c int mmc_register_card(struct mmc_card *c · line 305
Quoted 4 lines
drivers/mmc/mmc_sysfs.c +0
-0return ret; }It might be wise to also check the command classes here. I don't believe SDIO supports locking.
Quoted 3 lines
In this case, the lockable attribute will show "unlockable", which is the expected behavior. The lockable attribute will always be present, the card being lockable or not.
"unlockable" seems to be confusing.
"Unlockable" may mean something which is locked but can be unlocked (unlock-able). Or it may mean something which can't be locked (un-lockable).
Maybe returning "unsupported", "locked", "unlocked" etc would be clearer?
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: 2.6 Serial core