diff options
author | Jia-Ju Bai <baijiaju1990@gmail.com> | 2019-10-06 20:57:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-10-07 18:47:19 -0400 |
commit | 56e94ea132bb5c2c1d0b60a6aeb34dcb7d71a53d (patch) | |
tree | 3fe025b19f43bfe824b95256f2ad92a682cb754c | |
parent | 7a243c82ea527cd1da47381ad9cd646844f3b693 (diff) |
fs: ocfs2: fix possible null-pointer dereferences in ocfs2_xa_prepare_entry()
In ocfs2_xa_prepare_entry(), there is an if statement on line 2136 to
check whether loc->xl_entry is NULL:
if (loc->xl_entry)
When loc->xl_entry is NULL, it is used on line 2158:
ocfs2_xa_add_entry(loc, name_hash);
loc->xl_entry->xe_name_hash = cpu_to_le32(name_hash);
loc->xl_entry->xe_name_offset = cpu_to_le16(loc->xl_size);
and line 2164:
ocfs2_xa_add_namevalue(loc, xi);
loc->xl_entry->xe_value_size = cpu_to_le64(xi->xi_value_len);
loc->xl_entry->xe_name_len = xi->xi_name_len;
Thus, possible null-pointer dereferences may occur.
To fix these bugs, if loc-xl_entry is NULL, ocfs2_xa_prepare_entry()
abnormally returns with -EINVAL.
These bugs are found by a static analysis tool STCheck written by us.
[akpm@linux-foundation.org: remove now-unused ocfs2_xa_add_entry()]
Link: http://lkml.kernel.org/r/20190726101447.9153-1-baijiaju1990@gmail.com
Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Changwei Ge <gechangwei@live.cn>
Cc: Gang He <ghe@suse.com>
Cc: Jun Piao <piaojun@huawei.com>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/ocfs2/xattr.c | 56 |
1 files changed, 23 insertions, 33 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 90c830e3758e..d8507972ee13 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -1490,18 +1490,6 @@ static int ocfs2_xa_check_space(struct ocfs2_xa_loc *loc, | |||
1490 | return loc->xl_ops->xlo_check_space(loc, xi); | 1490 | return loc->xl_ops->xlo_check_space(loc, xi); |
1491 | } | 1491 | } |
1492 | 1492 | ||
1493 | static void ocfs2_xa_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash) | ||
1494 | { | ||
1495 | loc->xl_ops->xlo_add_entry(loc, name_hash); | ||
1496 | loc->xl_entry->xe_name_hash = cpu_to_le32(name_hash); | ||
1497 | /* | ||
1498 | * We can't leave the new entry's xe_name_offset at zero or | ||
1499 | * add_namevalue() will go nuts. We set it to the size of our | ||
1500 | * storage so that it can never be less than any other entry. | ||
1501 | */ | ||
1502 | loc->xl_entry->xe_name_offset = cpu_to_le16(loc->xl_size); | ||
1503 | } | ||
1504 | |||
1505 | static void ocfs2_xa_add_namevalue(struct ocfs2_xa_loc *loc, | 1493 | static void ocfs2_xa_add_namevalue(struct ocfs2_xa_loc *loc, |
1506 | struct ocfs2_xattr_info *xi) | 1494 | struct ocfs2_xattr_info *xi) |
1507 | { | 1495 | { |
@@ -2133,29 +2121,31 @@ static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc, | |||
2133 | if (rc) | 2121 | if (rc) |
2134 | goto out; | 2122 | goto out; |
2135 | 2123 | ||
2136 | if (loc->xl_entry) { | 2124 | if (!loc->xl_entry) { |
2137 | if (ocfs2_xa_can_reuse_entry(loc, xi)) { | 2125 | rc = -EINVAL; |
2138 | orig_value_size = loc->xl_entry->xe_value_size; | 2126 | goto out; |
2139 | rc = ocfs2_xa_reuse_entry(loc, xi, ctxt); | 2127 | } |
2140 | if (rc) | ||
2141 | goto out; | ||
2142 | goto alloc_value; | ||
2143 | } | ||
2144 | 2128 | ||
2145 | if (!ocfs2_xattr_is_local(loc->xl_entry)) { | 2129 | if (ocfs2_xa_can_reuse_entry(loc, xi)) { |
2146 | orig_clusters = ocfs2_xa_value_clusters(loc); | 2130 | orig_value_size = loc->xl_entry->xe_value_size; |
2147 | rc = ocfs2_xa_value_truncate(loc, 0, ctxt); | 2131 | rc = ocfs2_xa_reuse_entry(loc, xi, ctxt); |
2148 | if (rc) { | 2132 | if (rc) |
2149 | mlog_errno(rc); | 2133 | goto out; |
2150 | ocfs2_xa_cleanup_value_truncate(loc, | 2134 | goto alloc_value; |
2151 | "overwriting", | 2135 | } |
2152 | orig_clusters); | 2136 | |
2153 | goto out; | 2137 | if (!ocfs2_xattr_is_local(loc->xl_entry)) { |
2154 | } | 2138 | orig_clusters = ocfs2_xa_value_clusters(loc); |
2139 | rc = ocfs2_xa_value_truncate(loc, 0, ctxt); | ||
2140 | if (rc) { | ||
2141 | mlog_errno(rc); | ||
2142 | ocfs2_xa_cleanup_value_truncate(loc, | ||
2143 | "overwriting", | ||
2144 | orig_clusters); | ||
2145 | goto out; | ||
2155 | } | 2146 | } |
2156 | ocfs2_xa_wipe_namevalue(loc); | 2147 | } |
2157 | } else | 2148 | ocfs2_xa_wipe_namevalue(loc); |
2158 | ocfs2_xa_add_entry(loc, name_hash); | ||
2159 | 2149 | ||
2160 | /* | 2150 | /* |
2161 | * If we get here, we have a blank entry. Fill it. We grow our | 2151 | * If we get here, we have a blank entry. Fill it. We grow our |