Re: [PATCH 8/8] block: sed-opal: ioctl for writing to shadow mbr
Hi Jonas, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on next-20180309] [cannot apply to linus/master v4.16-rc4 v4.16-rc3 v4.16-rc2 v4.16-rc5] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Jonas-Rabenstein/block-sed-opal-support-write-to-shadow-mbr/20180314-184749 reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) block/sed-opal.c:381:20: sparse: incorrect type in assignment (different base types) @@expected unsigned long long [unsigned] [usertype] align @@ got ed long long [unsigned] [usertype] align @@ block/sed-opal.c:381:20:expected unsigned long long [unsigned] [usertype] align block/sed-opal.c:381:20:got restricted __be64 const [usertype] alignment_granularity block/sed-opal.c:382:25: sparse: incorrect type in assignment (different base types) @@expected unsigned long long [unsigned] [usertype] lowest_lba @@got ed long long [unsigned] [usertype] lowest_lba @@ block/sed-opal.c:382:25:expected unsigned long long [unsigned] [usertype] lowest_lba block/sed-opal.c:382:25:got restricted __be64 const [usertype] lowest_aligned_lba >> block/sed-opal.c:1526:58: sparse: incorrect type in argument 2 (different >> address spaces) @@expected void const [noderef] *from @@got >> unsvoid const [noderef] *from @@ block/sed-opal.c:1526:58:expected void const [noderef] *from block/sed-opal.c:1526:58:got unsigned char const [usertype] * >> block/sed-opal.c:2100:14: sparse: incorrect type in argument 1 (different >> address spaces) @@expected void const volatile [noderef] >> * @@got onst volatile [noderef] * @@ block/sed-opal.c:2100:14:expected void const volatile [noderef] * block/sed-opal.c:2100:14:got unsigned char const [usertype] *data vim +1526 block/sed-opal.c 1493 1494 static int write_shadow_mbr(struct opal_dev *dev, void *data) 1495 { 1496 struct opal_shadow_mbr *shadow = data; 1497 size_t off; 1498 u64 len; 1499 int err = 0; 1500 u8 *payload; 1501 1502 /* FIXME: this is the maximum we can use for IO_BUFFER_LENGTH=2048. 1503 *Instead of having constant, it would be nice to compute the 1504 *actual value depending on IO_BUFFER_LENGTH 1505 */ 1506 len = 1950; 1507 1508 /* do the actual transmission(s) */ 1509 for (off = 0 ; off < shadow->size; off += len) { 1510 len = min(len, shadow->size - off); 1511 1512 pr_debug("MBR: write bytes %zu+%llu/%llu\n", 1513 off, len, shadow->size); 1514 err = start_opal_cmd(dev, opaluid[OPAL_MBR], 1515 opalmethod[OPAL_SET]); 1516 add_token_u8(, dev, OPAL_STARTNAME); 1517 add_token_u8(, dev, OPAL_WHERE); 1518 add_token_u64(, dev, shadow->offset + off); 1519 add_token_u8(, dev, OPAL_ENDNAME); 1520 1521 add_token_u8(, dev, OPAL_STARTNAME); 1522 add_token_u8(, dev, OPAL_VALUES); 1523 payload = add_bytestring_header(, dev, len); 1524 if (!payload) 1525 break; > 1526 if (copy_from_user(payload, shadow->data + off, len)) 1527 err = -EFAULT; 1528 1529 add_token_u8(, dev, OPAL_ENDNAME); 1530 if (err) 1531 break; 1532 1533 err = finalize_and_send(dev, parse_and_check_status); 1534 if (err) 1535 break; 1536 } 1537 return err; 1538 } 1539 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [PATCH 8/8] block: sed-opal: ioctl for writing to shadow mbr
On Tue, Mar 13, 2018 at 02:09:01PM +0100, Jonas Rabenstein wrote: > Allow modification of the shadow mbr. If the shadow mbr is not marked as > done, this data will be presented read only as the device content. Only > after marking the shadow mbr as done and unlocking a locking range the > actual content is accessible. > > Signed-off-by: Jonas Rabenstein> +static int opal_write_shadow_mbr(struct opal_dev *dev, > + struct opal_shadow_mbr *info) > +{ > + const struct opal_step mbr_steps[] = { > + { opal_discovery0, }, > + { start_admin1LSP_opal_session, >key }, > + { write_shadow_mbr, info }, > + { end_opal_session, }, > + { NULL, } > + }; > + int ret; > + > + if (info->size == 0) > + return 0; We need to bound this to some maximum. I assume we'll at some point come across a controller with crappy firmware that wont check this against the MBR Table size and the user will either brick their drive or overwrite their data. We can get the size of the MBR Table it seems but I'm not sure how hard it is to pull that table yet. TCG SAS 5.7.3.6: The size of the MBR Table is retrievable from the "Table" table of the SP that incorporates the Locking Template. As always the TCG spec is super helpful /s. I will see how todo this and if it's worth it. > diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h > index 0cb9890cdc04..c2669ebff681 100644 > --- a/include/uapi/linux/sed-opal.h > +++ b/include/uapi/linux/sed-opal.h > @@ -104,6 +104,13 @@ struct opal_mbr_data { > __u8 __align[7]; > }; > > +struct opal_shadow_mbr { > + struct opal_key key; > + const __u8 *data; Please use a u64 here for the data and cast it to a pointer in the driver. We do this so we do not have to maintain a compat layer for 32 bit userland.
[PATCH 8/8] block: sed-opal: ioctl for writing to shadow mbr
Allow modification of the shadow mbr. If the shadow mbr is not marked as done, this data will be presented read only as the device content. Only after marking the shadow mbr as done and unlocking a locking range the actual content is accessible. Signed-off-by: Jonas Rabenstein--- block/sed-opal.c | 74 +++ include/linux/sed-opal.h | 1 + include/uapi/linux/sed-opal.h | 8 + 3 files changed, 83 insertions(+) diff --git a/block/sed-opal.c b/block/sed-opal.c index b201c96d23a3..1ec3734af656 100644 --- a/block/sed-opal.c +++ b/block/sed-opal.c @@ -1491,6 +1491,52 @@ static int set_mbr_enable_disable(struct opal_dev *dev, void *data) return finalize_and_send(dev, parse_and_check_status); } +static int write_shadow_mbr(struct opal_dev *dev, void *data) +{ + struct opal_shadow_mbr *shadow = data; + size_t off; + u64 len; + int err = 0; + u8 *payload; + + /* FIXME: this is the maximum we can use for IO_BUFFER_LENGTH=2048. +*Instead of having constant, it would be nice to compute the +*actual value depending on IO_BUFFER_LENGTH +*/ + len = 1950; + + /* do the actual transmission(s) */ + for (off = 0 ; off < shadow->size; off += len) { + len = min(len, shadow->size - off); + + pr_debug("MBR: write bytes %zu+%llu/%llu\n", +off, len, shadow->size); + err = start_opal_cmd(dev, opaluid[OPAL_MBR], +opalmethod[OPAL_SET]); + add_token_u8(, dev, OPAL_STARTNAME); + add_token_u8(, dev, OPAL_WHERE); + add_token_u64(, dev, shadow->offset + off); + add_token_u8(, dev, OPAL_ENDNAME); + + add_token_u8(, dev, OPAL_STARTNAME); + add_token_u8(, dev, OPAL_VALUES); + payload = add_bytestring_header(, dev, len); + if (!payload) + break; + if (copy_from_user(payload, shadow->data + off, len)) + err = -EFAULT; + + add_token_u8(, dev, OPAL_ENDNAME); + if (err) + break; + + err = finalize_and_send(dev, parse_and_check_status); + if (err) + break; + } + return err; +} + static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid, struct opal_dev *dev) { @@ -2036,6 +2082,31 @@ static int opal_mbr_status(struct opal_dev *dev, struct opal_mbr_data *opal_mbr) return ret; } +static int opal_write_shadow_mbr(struct opal_dev *dev, +struct opal_shadow_mbr *info) +{ + const struct opal_step mbr_steps[] = { + { opal_discovery0, }, + { start_admin1LSP_opal_session, >key }, + { write_shadow_mbr, info }, + { end_opal_session, }, + { NULL, } + }; + int ret; + + if (info->size == 0) + return 0; + + if (!access_ok(VERIFY_READ, info->data, info->size)) + return -EINVAL; + + mutex_lock(>dev_lock); + setup_opal_dev(dev, mbr_steps); + ret = next(dev); + mutex_unlock(>dev_lock); + return ret; +} + static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk) { struct opal_suspend_data *suspend; @@ -2368,6 +2439,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg) case IOC_OPAL_MBR_STATUS: ret = opal_mbr_status(dev, p); break; + case IOC_OPAL_WRITE_SHADOW_MBR: + ret = opal_write_shadow_mbr(dev, p); + break; case IOC_OPAL_ERASE_LR: ret = opal_erase_locking_range(dev, p); break; diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h index b38dc602cae3..cf08cdc13cbd 100644 --- a/include/linux/sed-opal.h +++ b/include/linux/sed-opal.h @@ -47,6 +47,7 @@ static inline bool is_sed_ioctl(unsigned int cmd) case IOC_OPAL_ENABLE_DISABLE_MBR: case IOC_OPAL_ERASE_LR: case IOC_OPAL_SECURE_ERASE_LR: + case IOC_OPAL_WRITE_SHADOW_MBR: case IOC_OPAL_MBR_STATUS: return true; } diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h index 0cb9890cdc04..c2669ebff681 100644 --- a/include/uapi/linux/sed-opal.h +++ b/include/uapi/linux/sed-opal.h @@ -104,6 +104,13 @@ struct opal_mbr_data { __u8 __align[7]; }; +struct opal_shadow_mbr { + struct opal_key key; + const __u8 *data; + __u64 offset; + __u64 size; +}; + #define IOC_OPAL_SAVE _IOW('p', 220, struct opal_lock_unlock) #define IOC_OPAL_LOCK_UNLOCK _IOW('p', 221, struct opal_lock_unlock) #define