diff --git a/debian/patches/bugfix/all/dentry-name-snapshots.patch b/debian/patches/bugfix/all/dentry-name-snapshots.patch deleted file mode 100644 index 1d12db5d1..000000000 --- a/debian/patches/bugfix/all/dentry-name-snapshots.patch +++ /dev/null @@ -1,242 +0,0 @@ -From: Al Viro -Date: Fri, 7 Jul 2017 14:51:19 -0400 -Subject: dentry name snapshots -Origin: https://git.kernel.org/linus/49d31c2f389acfe83417083e1208422b4091cd9e -Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-7533 - -take_dentry_name_snapshot() takes a safe snapshot of dentry name; -if the name is a short one, it gets copied into caller-supplied -structure, otherwise an extra reference to external name is grabbed -(those are never modified). In either case the pointer to stable -string is stored into the same structure. - -dentry must be held by the caller of take_dentry_name_snapshot(), -but may be freely dropped afterwards - the snapshot will stay -until destroyed by release_dentry_name_snapshot(). - -Intended use: - struct name_snapshot s; - - take_dentry_name_snapshot(&s, dentry); - ... - access s.name - ... - release_dentry_name_snapshot(&s); - -Replaces fsnotify_oldname_...(), gets used in fsnotify to obtain the name -to pass down with event. - -Signed-off-by: Al Viro ---- - fs/dcache.c | 27 +++++++++++++++++++++++++++ - fs/debugfs/inode.c | 10 +++++----- - fs/namei.c | 8 ++++---- - fs/notify/fsnotify.c | 8 ++++++-- - include/linux/dcache.h | 6 ++++++ - include/linux/fsnotify.h | 31 ------------------------------- - 6 files changed, 48 insertions(+), 42 deletions(-) - -diff --git a/fs/dcache.c b/fs/dcache.c -index b85da8897ffa..831f3a9a8f05 100644 ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -277,6 +277,33 @@ static inline int dname_external(const struct dentry *dentry) - return dentry->d_name.name != dentry->d_iname; - } - -+void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry) -+{ -+ spin_lock(&dentry->d_lock); -+ if (unlikely(dname_external(dentry))) { -+ struct external_name *p = external_name(dentry); -+ atomic_inc(&p->u.count); -+ spin_unlock(&dentry->d_lock); -+ name->name = p->name; -+ } else { -+ memcpy(name->inline_name, dentry->d_iname, DNAME_INLINE_LEN); -+ spin_unlock(&dentry->d_lock); -+ name->name = name->inline_name; -+ } -+} -+EXPORT_SYMBOL(take_dentry_name_snapshot); -+ -+void release_dentry_name_snapshot(struct name_snapshot *name) -+{ -+ if (unlikely(name->name != name->inline_name)) { -+ struct external_name *p; -+ p = container_of(name->name, struct external_name, name[0]); -+ if (unlikely(atomic_dec_and_test(&p->u.count))) -+ kfree_rcu(p, u.head); -+ } -+} -+EXPORT_SYMBOL(release_dentry_name_snapshot); -+ - static inline void __d_set_inode_and_type(struct dentry *dentry, - struct inode *inode, - unsigned type_flags) -diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c -index e892ae7d89f8..acd3be2cc691 100644 ---- a/fs/debugfs/inode.c -+++ b/fs/debugfs/inode.c -@@ -766,7 +766,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, - { - int error; - struct dentry *dentry = NULL, *trap; -- const char *old_name; -+ struct name_snapshot old_name; - - trap = lock_rename(new_dir, old_dir); - /* Source or destination directories don't exist? */ -@@ -781,19 +781,19 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, - if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry)) - goto exit; - -- old_name = fsnotify_oldname_init(old_dentry->d_name.name); -+ take_dentry_name_snapshot(&old_name, old_dentry); - - error = simple_rename(d_inode(old_dir), old_dentry, d_inode(new_dir), - dentry, 0); - if (error) { -- fsnotify_oldname_free(old_name); -+ release_dentry_name_snapshot(&old_name); - goto exit; - } - d_move(old_dentry, dentry); -- fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name, -+ fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name.name, - d_is_dir(old_dentry), - NULL, old_dentry); -- fsnotify_oldname_free(old_name); -+ release_dentry_name_snapshot(&old_name); - unlock_rename(new_dir, old_dir); - dput(dentry); - return old_dentry; -diff --git a/fs/namei.c b/fs/namei.c -index efe53a5d0737..c5588e837b15 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -4362,11 +4362,11 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - { - int error; - bool is_dir = d_is_dir(old_dentry); -- const unsigned char *old_name; - struct inode *source = old_dentry->d_inode; - struct inode *target = new_dentry->d_inode; - bool new_is_dir = false; - unsigned max_links = new_dir->i_sb->s_max_links; -+ struct name_snapshot old_name; - - if (source == target) - return 0; -@@ -4413,7 +4413,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - if (error) - return error; - -- old_name = fsnotify_oldname_init(old_dentry->d_name.name); -+ take_dentry_name_snapshot(&old_name, old_dentry); - dget(new_dentry); - if (!is_dir || (flags & RENAME_EXCHANGE)) - lock_two_nondirectories(source, target); -@@ -4468,14 +4468,14 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - inode_unlock(target); - dput(new_dentry); - if (!error) { -- fsnotify_move(old_dir, new_dir, old_name, is_dir, -+ fsnotify_move(old_dir, new_dir, old_name.name, is_dir, - !(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry); - if (flags & RENAME_EXCHANGE) { - fsnotify_move(new_dir, old_dir, old_dentry->d_name.name, - new_is_dir, NULL, new_dentry); - } - } -- fsnotify_oldname_free(old_name); -+ release_dentry_name_snapshot(&old_name); - - return error; - } -diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c -index 01a9f0f007d4..0c4583b61717 100644 ---- a/fs/notify/fsnotify.c -+++ b/fs/notify/fsnotify.c -@@ -161,16 +161,20 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask - if (unlikely(!fsnotify_inode_watches_children(p_inode))) - __fsnotify_update_child_dentry_flags(p_inode); - else if (p_inode->i_fsnotify_mask & mask) { -+ struct name_snapshot name; -+ - /* we are notifying a parent so come up with the new mask which - * specifies these are events which came from a child. */ - mask |= FS_EVENT_ON_CHILD; - -+ take_dentry_name_snapshot(&name, dentry); - if (path) - ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, -- dentry->d_name.name, 0); -+ name.name, 0); - else - ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, -- dentry->d_name.name, 0); -+ name.name, 0); -+ release_dentry_name_snapshot(&name); - } - - dput(parent); -diff --git a/include/linux/dcache.h b/include/linux/dcache.h -index d2e38dc6172c..025727bf6797 100644 ---- a/include/linux/dcache.h -+++ b/include/linux/dcache.h -@@ -591,5 +591,11 @@ static inline struct inode *d_real_inode(const struct dentry *dentry) - return d_backing_inode(d_real((struct dentry *) dentry, NULL, 0)); - } - -+struct name_snapshot { -+ const char *name; -+ char inline_name[DNAME_INLINE_LEN]; -+}; -+void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *); -+void release_dentry_name_snapshot(struct name_snapshot *); - - #endif /* __LINUX_DCACHE_H */ -diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h -index b43d3f5bd9ea..b78aa7ac77ce 100644 ---- a/include/linux/fsnotify.h -+++ b/include/linux/fsnotify.h -@@ -293,35 +293,4 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) - } - } - --#if defined(CONFIG_FSNOTIFY) /* notify helpers */ -- --/* -- * fsnotify_oldname_init - save off the old filename before we change it -- */ --static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name) --{ -- return kstrdup(name, GFP_KERNEL); --} -- --/* -- * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init -- */ --static inline void fsnotify_oldname_free(const unsigned char *old_name) --{ -- kfree(old_name); --} -- --#else /* CONFIG_FSNOTIFY */ -- --static inline const char *fsnotify_oldname_init(const unsigned char *name) --{ -- return NULL; --} -- --static inline void fsnotify_oldname_free(const unsigned char *old_name) --{ --} -- --#endif /* CONFIG_FSNOTIFY */ -- - #endif /* _LINUX_FS_NOTIFY_H */ --- -2.11.0 -