Limit exposure of dentry and inode creation
authorEric Biggers <ebiggers3@gmail.com>
Wed, 25 Mar 2015 01:46:01 +0000 (20:46 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Thu, 26 Mar 2015 00:56:37 +0000 (19:56 -0500)
- Don't allow creating d_inode=NULL dentries outside of dentry.c
- Don't allow creating i_nlink=0 inodes

include/wimlib/dentry.h
include/wimlib/inode.h
src/dentry.c
src/inode.c
src/inode_table.c
src/mount_image.c

index 241dc56..cb0f330 100644 (file)
@@ -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);
index 28285b2..1818d10 100644 (file)
@@ -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) \
index 55da50c..302409f 100644 (file)
@@ -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;
 
index 1114a15..e6da509 100644 (file)
  */
 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;
 }
 
index f6de4e6..1a1fba6 100644 (file)
@@ -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;
index dd6d94c..10fc61c 100644 (file)
@@ -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;