diff --git a/debian/changelog b/debian/changelog index cf9b597da..b61c693fe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,6 +16,8 @@ linux (4.17.2-1) UNRELEASED; urgency=medium (CVE-2018-10840) * ext4: do not allow external inodes for inline data (CVE-2018-11412) * ext4: bubble errors from ext4_find_inline_data_nolock() up to ext4_iget() + * socket: close race condition between sock_close() and sockfs_setattr() + (CVE-2018-12232) [ Romain Perier ] * [x86] Enable DCN 1.0 Raven family (Closes #901349) diff --git a/debian/patches/bugfix/all/socket-close-race-condition-between-sock_close-and-s.patch b/debian/patches/bugfix/all/socket-close-race-condition-between-sock_close-and-s.patch new file mode 100644 index 000000000..1c8c8e56b --- /dev/null +++ b/debian/patches/bugfix/all/socket-close-race-condition-between-sock_close-and-s.patch @@ -0,0 +1,87 @@ +From: Cong Wang +Date: Thu, 7 Jun 2018 13:39:49 -0700 +Subject: socket: close race condition between sock_close() and + sockfs_setattr() +Origin: https://git.kernel.org/linus/6d8c50dcb029872b298eea68cc6209c866fd3e14 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2018-12232 + +fchownat() doesn't even hold refcnt of fd until it figures out +fd is really needed (otherwise is ignored) and releases it after +it resolves the path. This means sock_close() could race with +sockfs_setattr(), which leads to a NULL pointer dereference +since typically we set sock->sk to NULL in ->release(). + +As pointed out by Al, this is unique to sockfs. So we can fix this +in socket layer by acquiring inode_lock in sock_close() and +checking against NULL in sockfs_setattr(). + +sock_release() is called in many places, only the sock_close() +path matters here. And fortunately, this should not affect normal +sock_close() as it is only called when the last fd refcnt is gone. +It only affects sock_close() with a parallel sockfs_setattr() in +progress, which is not common. + +Fixes: 86741ec25462 ("net: core: Add a UID field to struct sock.") +Reported-by: shankarapailoor +Cc: Tetsuo Handa +Cc: Lorenzo Colitti +Cc: Al Viro +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +--- + net/socket.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/net/socket.c ++++ b/net/socket.c +@@ -537,7 +537,10 @@ static int sockfs_setattr(struct dentry + if (!err && (iattr->ia_valid & ATTR_UID)) { + struct socket *sock = SOCKET_I(d_inode(dentry)); + +- sock->sk->sk_uid = iattr->ia_uid; ++ if (sock->sk) ++ sock->sk->sk_uid = iattr->ia_uid; ++ else ++ err = -ENOENT; + } + + return err; +@@ -586,12 +589,16 @@ EXPORT_SYMBOL(sock_alloc); + * an inode not a file. + */ + +-void sock_release(struct socket *sock) ++static void __sock_release(struct socket *sock, struct inode *inode) + { + if (sock->ops) { + struct module *owner = sock->ops->owner; + ++ if (inode) ++ inode_lock(inode); + sock->ops->release(sock); ++ if (inode) ++ inode_unlock(inode); + sock->ops = NULL; + module_put(owner); + } +@@ -605,6 +612,11 @@ void sock_release(struct socket *sock) + } + sock->file = NULL; + } ++ ++void sock_release(struct socket *sock) ++{ ++ __sock_release(sock, NULL); ++} + EXPORT_SYMBOL(sock_release); + + void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags) +@@ -1146,7 +1158,7 @@ static int sock_mmap(struct file *file, + + static int sock_close(struct inode *inode, struct file *filp) + { +- sock_release(SOCKET_I(inode)); ++ __sock_release(SOCKET_I(inode), inode); + return 0; + } + diff --git a/debian/patches/series b/debian/patches/series index b3fa76dbc..d55902246 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -129,6 +129,7 @@ bugfix/all/vhost-fix-info-leak-due-to-uninitialized-memory.patch bugfix/all/ext4-correctly-handle-a-zero-length-xattr-with-a-non.patch bugfix/all/ext4-do-not-allow-external-inodes-for-inline-data.patch bugfix/all/ext4-bubble-errors-from-ext4_find_inline_data_nolock.patch +bugfix/all/socket-close-race-condition-between-sock_close-and-s.patch # Fix exported symbol versions bugfix/all/module-disable-matching-missing-version-crc.patch