Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secstor anti-rollback #1630

Merged
merged 4 commits into from
Jun 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions core/include/tee/fs_dirfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct tee_fs_dirfile_fileh {
* @commit_writes: commits changes since the file was opened
*/
struct tee_fs_dirfile_operations {
TEE_Result (*open)(bool create, const TEE_UUID *uuid,
TEE_Result (*open)(bool create, uint8_t *hash, const TEE_UUID *uuid,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You forgot to update comment above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, I don't get it. Which comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I'm sorry. That was structure description, not function description. Please ignore this.

struct tee_fs_dirfile_fileh *dfh,
struct tee_file_handle **fh);
void (*close)(struct tee_file_handle *fh);
Expand All @@ -69,10 +69,14 @@ struct tee_fs_dirfile_operations {

/**
* tee_fs_dirfile_open() - opens a dirfile handle
* @create: true if a new dirfile is to be created, else the dirfile
* is read opened and verified
* @hash: hash of underlying file
* @fops: file interface
* @dirh: returned dirfile handle
*/
TEE_Result tee_fs_dirfile_open(const struct tee_fs_dirfile_operations *fops,
TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash,
const struct tee_fs_dirfile_operations *fops,
struct tee_fs_dirfile_dirh **dirh);
/**
* tee_fs_dirfile_close() - closes a dirfile handle
Expand All @@ -86,8 +90,10 @@ void tee_fs_dirfile_close(struct tee_fs_dirfile_dirh *dirh);
/**
* tee_fs_dirfile_commit_writes() - commit updates of dirfile
* @dirh: dirfile handle
* @hash: hash of underlying file is copied here if not NULL
*/
TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh);
TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh,
uint8_t *hash);

/**
* tee_fs_dirfile_get_tmp() - get a temporary file handle
Expand Down
3 changes: 3 additions & 0 deletions core/include/tee/tee_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ extern const struct tee_file_operations ree_fs_ops;
#endif
#ifdef CFG_RPMB_FS
extern const struct tee_file_operations rpmb_fs_ops;

TEE_Result tee_rpmb_fs_raw_open(const char *fname, bool create,
struct tee_file_handle **fh);
#endif

#endif /*TEE_FS_H*/
17 changes: 8 additions & 9 deletions core/tee/fs_dirfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ static TEE_Result write_dent(struct tee_fs_dirfile_dirh *dirh, size_t n,
return res;
}

TEE_Result tee_fs_dirfile_open(const struct tee_fs_dirfile_operations *fops,
TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash,
const struct tee_fs_dirfile_operations *fops,
struct tee_fs_dirfile_dirh **dirh_ret)
{
TEE_Result res;
Expand All @@ -140,12 +141,9 @@ TEE_Result tee_fs_dirfile_open(const struct tee_fs_dirfile_operations *fops,
return TEE_ERROR_OUT_OF_MEMORY;

dirh->fops = fops;
res = fops->open(false, NULL, NULL, &dirh->fh);
if (res) {
res = fops->open(true, NULL, NULL, &dirh->fh);
if (res)
goto out;
}
res = fops->open(create, hash, NULL, NULL, &dirh->fh);
if (res)
goto out;

for (n = 0;; n++) {
struct dirfile_entry dent;
Expand Down Expand Up @@ -193,9 +191,10 @@ void tee_fs_dirfile_close(struct tee_fs_dirfile_dirh *dirh)
}
}

TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh)
TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh,
uint8_t *hash)
{
return dirh->fops->commit_writes(dirh->fh, NULL);
return dirh->fops->commit_writes(dirh->fh, hash);
}

TEE_Result tee_fs_dirfile_get_tmp(struct tee_fs_dirfile_dirh *dirh,
Expand Down
133 changes: 101 additions & 32 deletions core/tee/tee_ree_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,13 @@ static TEE_Result ree_fs_write_primitive(struct tee_file_handle *fh, size_t pos,
return out_of_place_write(fdp, pos, buf, len);
}

static TEE_Result ree_fs_open_primitive(bool create, const TEE_UUID *uuid,
static TEE_Result ree_fs_open_primitive(bool create, uint8_t *hash,
const TEE_UUID *uuid,
struct tee_fs_dirfile_fileh *dfh,
struct tee_file_handle **fh)
{
TEE_Result res;
struct tee_fs_fd *fdp;
uint8_t *hash = NULL;

fdp = calloc(1, sizeof(struct tee_fs_fd));
if (!fdp)
Expand All @@ -404,8 +404,6 @@ static TEE_Result ree_fs_open_primitive(bool create, const TEE_UUID *uuid,
if (res != TEE_SUCCESS)
goto out;

if (dfh)
hash = dfh->hash;
res = tee_fs_htree_open(create, hash, uuid, &ree_fs_storage_ops,
fdp, &fdp->ht);
out:
Expand Down Expand Up @@ -462,39 +460,110 @@ static const struct tee_fs_dirfile_operations ree_dirf_ops = {
static struct tee_fs_dirfile_dirh *ree_fs_dirh;
static size_t ree_fs_dirh_refcount;

static TEE_Result get_dirh(struct tee_fs_dirfile_dirh **dirh)
#ifdef CFG_RPMB_FS
static struct tee_file_handle *ree_fs_rpmb_fh;

static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh)
{
if (!ree_fs_dirh_refcount) {
TEE_Result res;
TEE_Result res;
uint8_t hash[TEE_FS_HTREE_HASH_SIZE];
uint8_t *hashp = NULL;
const char fname[] = "dirfile.db.hash";

assert(!ree_fs_dirh);
res = tee_fs_dirfile_open(&ree_dirf_ops, &ree_fs_dirh);
res = tee_rpmb_fs_raw_open(fname, false, &ree_fs_rpmb_fh);
if (!res) {
size_t l = sizeof(hash);

res = rpmb_fs_ops.read(ree_fs_rpmb_fh, 0, hash, &l);
if (res)
return res;
if (l == sizeof(hash))
hashp = hash;
} else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
res = tee_rpmb_fs_raw_open(fname, true, &ree_fs_rpmb_fh);
}
if (res)
return res;

if (!tee_fs_dirfile_open(false, hashp, &ree_dirf_ops, dirh))
return TEE_SUCCESS;

res = tee_fs_dirfile_open(true, NULL, &ree_dirf_ops, dirh);
if (res)
rpmb_fs_ops.close(&ree_fs_rpmb_fh);
return res;
}

static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh)
{
TEE_Result res;
uint8_t hash[TEE_FS_HTREE_HASH_SIZE];

res = tee_fs_dirfile_commit_writes(dirh, hash);
if (res)
return res;
return rpmb_fs_ops.write(ree_fs_rpmb_fh, 0, hash, sizeof(hash));
}

static void close_dirh(struct tee_fs_dirfile_dirh **dirh)
{
tee_fs_dirfile_close(*dirh);
*dirh = NULL;
rpmb_fs_ops.close(&ree_fs_rpmb_fh);
}

#else /*!CFG_RPMB_FS*/
static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh)
{
if (!tee_fs_dirfile_open(false, NULL, &ree_dirf_ops, dirh))
return TEE_SUCCESS;
return tee_fs_dirfile_open(true, NULL, &ree_dirf_ops, dirh);
}

static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh)
{
return tee_fs_dirfile_commit_writes(dirh, NULL);
}

static void close_dirh(struct tee_fs_dirfile_dirh **dirh)
{
tee_fs_dirfile_close(*dirh);
*dirh = NULL;
}
#endif /*!CFG_RPMB_FS*/

static TEE_Result get_dirh(struct tee_fs_dirfile_dirh **dirh)
{
if (!ree_fs_dirh) {
TEE_Result res = open_dirh(&ree_fs_dirh);

if (res) {
*dirh = NULL;
return res;
}
}
assert(ree_fs_dirh);
ree_fs_dirh_refcount++;
assert(ree_fs_dirh);
assert(ree_fs_dirh_refcount);
*dirh = ree_fs_dirh;
return TEE_SUCCESS;
}

static void put_dirh_primitive(void)
static void put_dirh_primitive(bool close)
{
assert(ree_fs_dirh_refcount);
assert(ree_fs_dirh);

ree_fs_dirh_refcount--;
if (!ree_fs_dirh_refcount) {
tee_fs_dirfile_close(ree_fs_dirh);
ree_fs_dirh = NULL;
}
if (!ree_fs_dirh_refcount || close)
close_dirh(&ree_fs_dirh);
}

static void put_dirh(struct tee_fs_dirfile_dirh *dirh)
static void put_dirh(struct tee_fs_dirfile_dirh *dirh, bool close)
{
if (dirh) {
assert(dirh == ree_fs_dirh);
put_dirh_primitive();
put_dirh_primitive(close);
}
}

Expand All @@ -516,7 +585,7 @@ static TEE_Result ree_fs_open(struct tee_pobj *po, size_t *size,
if (res != TEE_SUCCESS)
goto out;

res = ree_fs_open_primitive(false, &po->uuid, &dfh, fh);
res = ree_fs_open_primitive(false, dfh.hash, &po->uuid, &dfh, fh);
if (res == TEE_ERROR_ITEM_NOT_FOUND) {
/*
* If the object isn't found someone has tampered with it,
Expand All @@ -531,7 +600,7 @@ static TEE_Result ree_fs_open(struct tee_pobj *po, size_t *size,

out:
if (res)
put_dirh(dirh);
put_dirh(dirh, false);
mutex_unlock(&ree_fs_mutex);

return res;
Expand Down Expand Up @@ -564,7 +633,7 @@ static TEE_Result set_name(struct tee_fs_dirfile_dirh *dirh,
if (res)
return res;

res = tee_fs_dirfile_commit_writes(dirh);
res = commit_dirh_writes(dirh);
if (res)
return res;

Expand All @@ -578,7 +647,7 @@ static void ree_fs_close(struct tee_file_handle **fh)
{
if (*fh) {
mutex_lock(&ree_fs_mutex);
put_dirh_primitive();
put_dirh_primitive(false);
mutex_unlock(&ree_fs_mutex);

ree_fs_close_primitive(*fh);
Expand Down Expand Up @@ -609,7 +678,7 @@ static TEE_Result ree_fs_create(struct tee_pobj *po, bool overwrite,
if (res)
goto out;

res = ree_fs_open_primitive(true, &po->uuid, &dfh, fh);
res = ree_fs_open_primitive(true, dfh.hash, &po->uuid, &dfh, fh);
if (res)
goto out;

Expand Down Expand Up @@ -641,7 +710,7 @@ static TEE_Result ree_fs_create(struct tee_pobj *po, bool overwrite,
res = set_name(dirh, fdp, po, overwrite);
out:
if (res) {
put_dirh(dirh);
put_dirh(dirh, true);
if (*fh) {
ree_fs_close_primitive(*fh);
*fh = NULL;
Expand Down Expand Up @@ -677,9 +746,9 @@ static TEE_Result ree_fs_write(struct tee_file_handle *fh, size_t pos,
res = tee_fs_dirfile_update_hash(dirh, &fdp->dfh);
if (res)
goto out;
res = tee_fs_dirfile_commit_writes(dirh);
res = commit_dirh_writes(dirh);
out:
put_dirh(dirh);
put_dirh(dirh, res);
mutex_unlock(&ree_fs_mutex);

return res;
Expand Down Expand Up @@ -724,15 +793,15 @@ static TEE_Result ree_fs_rename(struct tee_pobj *old, struct tee_pobj *new,
goto out;
}

res = tee_fs_dirfile_commit_writes(dirh);
res = commit_dirh_writes(dirh);
if (res)
goto out;

if (remove_dfh.idx != -1)
tee_fs_rpc_remove_dfh(OPTEE_MSG_RPC_CMD_FS, &remove_dfh);

out:
put_dirh(dirh);
put_dirh(dirh, res);
mutex_unlock(&ree_fs_mutex);

return res;
Expand All @@ -759,7 +828,7 @@ static TEE_Result ree_fs_remove(struct tee_pobj *po)
if (res)
goto out;

res = tee_fs_dirfile_commit_writes(dirh);
res = commit_dirh_writes(dirh);
if (res)
goto out;

Expand All @@ -768,7 +837,7 @@ static TEE_Result ree_fs_remove(struct tee_pobj *po)
assert(tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len,
&dfh));
out:
put_dirh(dirh);
put_dirh(dirh, res);
mutex_unlock(&ree_fs_mutex);

return res;
Expand Down Expand Up @@ -797,7 +866,7 @@ static TEE_Result ree_fs_truncate(struct tee_file_handle *fh, size_t len)
res = tee_fs_dirfile_update_hash(dirh, &fdp->dfh);

out:
put_dirh(dirh);
put_dirh(dirh, res);
mutex_unlock(&ree_fs_mutex);

return res;
Expand Down Expand Up @@ -833,7 +902,7 @@ static TEE_Result ree_fs_opendir_rpc(const TEE_UUID *uuid,
*dir = d;
} else {
if (d)
put_dirh(d->dirh);
put_dirh(d->dirh, false);
free(d);
}
mutex_unlock(&ree_fs_mutex);
Expand All @@ -846,7 +915,7 @@ static void ree_fs_closedir_rpc(struct tee_fs_dir *d)
if (d) {
mutex_lock(&ree_fs_mutex);

put_dirh(d->dirh);
put_dirh(d->dirh, false);
free(d);

mutex_unlock(&ree_fs_mutex);
Expand Down
Loading