jfs: Fix usercopy whitelist for inline inode data
Bart Massey reported what turned out to be a usercopy whitelist false
positive in JFS when symlink contents exceeded 128 bytes. The inline
inode data (i_inline) is actually designed to overflow into the "extended
area" following it (i_inline_ea) when needed. So the whitelist needed to
be expanded to include both i_inline and i_inline_ea (the whole size
of which is calculated internally using IDATASIZE, 256, instead of
sizeof(i_inline), 128).
$ cd /mnt/jfs
$ touch $(perl -e 'print "B" x 250')
$ ln -s B* b
$ ls -l >/dev/null
[ 249.436410] Bad or missing usercopy whitelist? Kernel memory exposure attempt detected from SLUB object 'jfs_ip' (offset 616, size 250)!
Reported-by: Bart Massey <bart.massey@gmail.com>
Fixes: 8d2704d382
("jfs: Define usercopy region in jfs_ip slab cache")
Cc: Dave Kleikamp <shaggy@kernel.org>
Cc: jfs-discussion@lists.sourceforge.net
Cc: stable@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
Родитель
7daf201d7f
Коммит
961b33c244
|
@ -115,6 +115,13 @@ struct dinode {
|
|||
dxd_t _dxd; /* 16: */
|
||||
union {
|
||||
__le32 _rdev; /* 4: */
|
||||
/*
|
||||
* The fast symlink area
|
||||
* is expected to overflow
|
||||
* into _inlineea when
|
||||
* needed (which will clear
|
||||
* INLINEEA).
|
||||
*/
|
||||
u8 _fastsymlink[128];
|
||||
} _u;
|
||||
u8 _inlineea[128];
|
||||
|
|
|
@ -87,6 +87,7 @@ struct jfs_inode_info {
|
|||
struct {
|
||||
unchar _unused[16]; /* 16: */
|
||||
dxd_t _dxd; /* 16: */
|
||||
/* _inline may overflow into _inline_ea when needed */
|
||||
unchar _inline[128]; /* 128: inline symlink */
|
||||
/* _inline_ea may overlay the last part of
|
||||
* file._xtroot if maxentry = XTROOTINITSLOT
|
||||
|
|
|
@ -967,8 +967,7 @@ static int __init init_jfs_fs(void)
|
|||
jfs_inode_cachep =
|
||||
kmem_cache_create_usercopy("jfs_ip", sizeof(struct jfs_inode_info),
|
||||
0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|SLAB_ACCOUNT,
|
||||
offsetof(struct jfs_inode_info, i_inline),
|
||||
sizeof_field(struct jfs_inode_info, i_inline),
|
||||
offsetof(struct jfs_inode_info, i_inline), IDATASIZE,
|
||||
init_once);
|
||||
if (jfs_inode_cachep == NULL)
|
||||
return -ENOMEM;
|
||||
|
|
Загрузка…
Ссылка в новой задаче