From: Eric Biggers Date: Wed, 25 Mar 2015 01:46:01 +0000 (-0500) Subject: Limit exposure of dentry and inode creation X-Git-Tag: v1.8.1~68 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=43a26b833482fc019c7aeee95656b8f2f3077db7 Limit exposure of dentry and inode creation - Don't allow creating d_inode=NULL dentries outside of dentry.c - Don't allow creating i_nlink=0 inodes --- diff --git a/include/wimlib/dentry.h b/include/wimlib/dentry.h index 241dc56d..cb0f330b 100644 --- a/include/wimlib/dentry.h +++ b/include/wimlib/dentry.h @@ -231,13 +231,12 @@ extern tchar * dentry_full_path(struct wim_dentry *dentry); extern int -new_dentry(const tchar *name, struct wim_dentry **dentry_ret); +new_dentry_with_new_inode(const tchar *name, bool set_timestamps, + struct wim_dentry **dentry_ret); extern int -new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret); - -extern int -new_dentry_with_timeless_inode(const tchar *name, struct wim_dentry **dentry_ret); +new_dentry_with_existing_inode(const tchar *name, struct wim_inode *inode, + struct wim_dentry **dentry_ret); extern void dentry_tree_clear_inode_visited(struct wim_dentry *root); diff --git a/include/wimlib/inode.h b/include/wimlib/inode.h index 28285b2b..1818d108 100644 --- a/include/wimlib/inode.h +++ b/include/wimlib/inode.h @@ -281,10 +281,7 @@ struct wim_inode { #define FILE_ATTRIBUTE_VIRTUAL 0x00010000 extern struct wim_inode * -new_inode(void) _malloc_attribute; - -extern struct wim_inode * -new_timeless_inode(void) _malloc_attribute; +new_inode(struct wim_dentry *dentry, bool set_timestamps); /* Iterate through each alias of the specified inode. */ #define inode_for_each_dentry(dentry, inode) \ diff --git a/src/dentry.c b/src/dentry.c index 55da50cf..302409f9 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -914,7 +914,7 @@ get_parent_dentry(WIMStruct *wim, const tchar *path, * *dentry_ret. On failure, returns WIMLIB_ERR_NOMEM or an error code resulting * from a failed string conversion. */ -int +static int new_dentry(const tchar *name, struct wim_dentry **dentry_ret) { struct wim_dentry *dentry; @@ -936,9 +936,12 @@ new_dentry(const tchar *name, struct wim_dentry **dentry_ret) return 0; } -static int -_new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret, - bool timeless) +/* Like new_dentry(), but also allocate an inode and associate it with the + * dentry. If set_timestamps=true, the timestamps for the inode will be set to + * the current time; otherwise, they will be left 0. */ +int +new_dentry_with_new_inode(const tchar *name, bool set_timestamps, + struct wim_dentry **dentry_ret) { struct wim_dentry *dentry; struct wim_inode *inode; @@ -948,36 +951,28 @@ _new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret, if (ret) return ret; - if (timeless) - inode = new_timeless_inode(); - else - inode = new_inode(); + inode = new_inode(dentry, set_timestamps); if (!inode) { free_dentry(dentry); return WIMLIB_ERR_NOMEM; } - d_associate(dentry, inode); - *dentry_ret = dentry; return 0; } -/* Like new_dentry(), but also allocate an inode and associate it with the - * dentry. The timestamps for the inode will be set to the current time. */ +/* Like new_dentry(), but also associate the new dentry with the specified inode + * and acquire a reference to each of the inode's blobs. */ int -new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret) +new_dentry_with_existing_inode(const tchar *name, struct wim_inode *inode, + struct wim_dentry **dentry_ret) { - return _new_dentry_with_inode(name, dentry_ret, false); -} - -/* Like new_dentry_with_inode(), but don't bother setting the timestamps for the - * new inode; instead, just leave them as 0, under the presumption that the - * caller will set them itself. */ -int -new_dentry_with_timeless_inode(const tchar *name, struct wim_dentry **dentry_ret) -{ - return _new_dentry_with_inode(name, dentry_ret, true); + int ret = new_dentry(name, dentry_ret); + if (ret) + return ret; + d_associate(*dentry_ret, inode); + inode_ref_blobs(inode); + return 0; } /* Create an unnamed dentry with a new inode for a directory with the default @@ -988,7 +983,7 @@ new_filler_directory(struct wim_dentry **dentry_ret) int ret; struct wim_dentry *dentry; - ret = new_dentry_with_inode(NULL, &dentry); + ret = new_dentry_with_new_inode(NULL, true, &dentry); if (ret) return ret; /* Leave the inode number as 0; this is allowed for non @@ -1449,7 +1444,7 @@ read_dentry(const u8 * restrict buf, size_t buf_len, return WIMLIB_ERR_INVALID_METADATA_RESOURCE; /* Allocate new dentry structure, along with a preliminary inode. */ - ret = new_dentry_with_timeless_inode(NULL, &dentry); + ret = new_dentry_with_new_inode(NULL, false, &dentry); if (ret) return ret; diff --git a/src/inode.c b/src/inode.c index 1114a153..e6da5095 100644 --- a/src/inode.c +++ b/src/inode.c @@ -44,32 +44,28 @@ */ const utf16lechar NO_STREAM_NAME[1]; -/* Allocate a new inode. Set the timestamps to the current time. */ +/* Allocate a new inode and associate the specified dentry with it. */ struct wim_inode * -new_inode(void) +new_inode(struct wim_dentry *dentry, bool set_timestamps) { - struct wim_inode *inode = new_timeless_inode(); - if (inode) { + struct wim_inode *inode; + + inode = CALLOC(1, sizeof(struct wim_inode)); + if (!inode) + return NULL; + + inode->i_security_id = -1; + /*inode->i_nlink = 0;*/ + inode->i_not_rpfixed = 1; + INIT_LIST_HEAD(&inode->i_list); + INIT_LIST_HEAD(&inode->i_dentry); + if (set_timestamps) { u64 now = now_as_wim_timestamp(); inode->i_creation_time = now; inode->i_last_access_time = now; inode->i_last_write_time = now; } - return inode; -} - -/* Allocate a new inode. Leave the timestamps zeroed out. */ -struct wim_inode * -new_timeless_inode(void) -{ - struct wim_inode *inode = CALLOC(1, sizeof(struct wim_inode)); - if (inode) { - inode->i_security_id = -1; - /*inode->i_nlink = 0;*/ - inode->i_not_rpfixed = 1; - INIT_LIST_HEAD(&inode->i_list); - INIT_LIST_HEAD(&inode->i_dentry); - } + d_associate(dentry, inode); return inode; } diff --git a/src/inode_table.c b/src/inode_table.c index f6de4e60..1a1fba69 100644 --- a/src/inode_table.c +++ b/src/inode_table.c @@ -96,7 +96,7 @@ inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, if (noshare) { /* File that cannot be hardlinked--- Return a new inode with its * inode and device numbers left at 0. */ - ret = new_dentry_with_timeless_inode(name, &dentry); + ret = new_dentry_with_new_inode(name, false, &dentry); if (ret) return ret; list_add_tail(&dentry->d_inode->i_list, &table->extra_inodes); @@ -105,35 +105,25 @@ inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, struct hlist_node *cur; /* File that can be hardlinked--- search the table for an - * existing inode matching the inode number and device; - * otherwise create a new inode. */ - ret = new_dentry(name, &dentry); - if (ret) - return ret; - - /* Search for an existing inode having the same inode number and - * device number. */ + * existing inode matching the inode number and device. */ pos = hash_u64(hash_u64(ino) + hash_u64(devno)) % table->capacity; hlist_for_each_entry(inode, cur, &table->array[pos], i_hlist) { if (inode->i_ino == ino && inode->i_devno == devno) { /* Found; use the existing inode. */ - inode_ref_blobs(inode); - goto have_inode; + return new_dentry_with_existing_inode(name, inode, + dentry_ret); } } - /* Create a new inode and insert it into the table. */ - inode = new_timeless_inode(); - if (!inode) { - free_dentry(dentry); - return WIMLIB_ERR_NOMEM; - } + /* Not found; create a new inode and add it to the table. */ + ret = new_dentry_with_new_inode(name, false, &dentry); + if (ret) + return ret; + inode = dentry->d_inode; inode->i_ino = ino; inode->i_devno = devno; hlist_add_head(&inode->i_hlist, &table->array[pos]); table->num_entries++; - have_inode: - d_associate(dentry, inode); } *dentry_ret = dentry; return 0; diff --git a/src/mount_image.c b/src/mount_image.c index dd6d94c6..10fc61cc 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -480,7 +480,7 @@ create_dentry(struct fuse_context *fuse_ctx, const char *path, if (get_dentry_child_with_name(parent, basename, WIMLIB_CASE_SENSITIVE)) return -EEXIST; - if (new_dentry_with_inode(basename, &new_dentry)) + if (new_dentry_with_new_inode(basename, true, &new_dentry)) return -ENOMEM; new_inode = new_dentry->d_inode; @@ -1405,11 +1405,9 @@ wimfs_link(const char *existing_path, const char *new_path) if (get_dentry_child_with_name(dir, new_name, WIMLIB_CASE_SENSITIVE)) return -EEXIST; - if (new_dentry(new_name, &new_alias)) + if (new_dentry_with_existing_inode(new_name, inode, &new_alias)) return -ENOMEM; - inode_ref_blobs(inode); - d_associate(new_alias, inode); dentry_add_child(dir, new_alias); touch_inode(dir->d_inode); return 0;