diff options
author | Dan Carpenter <dan.carpenter@oracle.com> | 2013-04-29 18:05:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 18:54:27 -0400 |
commit | 85a258b70d4891a443583530f48ab734a31e2d8d (patch) | |
tree | 9a02a047442e396a163e4014467258222d696ccd /fs | |
parent | 7ebab4536958b05f65b71ec312073acf5d66578d (diff) |
ocfs2: fix error handling in ocfs2_ioctl_move_extents()
Smatch complains that if we hit an error (for example if the file is
immutable) then "range" has uninitialized stack data and we copy it to
the user.
I've re-written the error handling to avoid this problem and make it a
little cleaner as well.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jie Liu <jeff.liu@oracle.com>
Reviewed-by: Jie Liu <jeff.liu@oracle.com>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/move_extents.c | 37 |
1 files changed, 17 insertions, 20 deletions
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 9f8dcadd9a50..8f3d3cb7fa97 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
@@ -1057,42 +1057,40 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp) | |||
1057 | 1057 | ||
1058 | struct inode *inode = file_inode(filp); | 1058 | struct inode *inode = file_inode(filp); |
1059 | struct ocfs2_move_extents range; | 1059 | struct ocfs2_move_extents range; |
1060 | struct ocfs2_move_extents_context *context = NULL; | 1060 | struct ocfs2_move_extents_context *context; |
1061 | |||
1062 | if (!argp) | ||
1063 | return -EINVAL; | ||
1061 | 1064 | ||
1062 | status = mnt_want_write_file(filp); | 1065 | status = mnt_want_write_file(filp); |
1063 | if (status) | 1066 | if (status) |
1064 | return status; | 1067 | return status; |
1065 | 1068 | ||
1066 | if ((!S_ISREG(inode->i_mode)) || !(filp->f_mode & FMODE_WRITE)) | 1069 | if ((!S_ISREG(inode->i_mode)) || !(filp->f_mode & FMODE_WRITE)) |
1067 | goto out; | 1070 | goto out_drop; |
1068 | 1071 | ||
1069 | if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) { | 1072 | if (inode->i_flags & (S_IMMUTABLE|S_APPEND)) { |
1070 | status = -EPERM; | 1073 | status = -EPERM; |
1071 | goto out; | 1074 | goto out_drop; |
1072 | } | 1075 | } |
1073 | 1076 | ||
1074 | context = kzalloc(sizeof(struct ocfs2_move_extents_context), GFP_NOFS); | 1077 | context = kzalloc(sizeof(struct ocfs2_move_extents_context), GFP_NOFS); |
1075 | if (!context) { | 1078 | if (!context) { |
1076 | status = -ENOMEM; | 1079 | status = -ENOMEM; |
1077 | mlog_errno(status); | 1080 | mlog_errno(status); |
1078 | goto out; | 1081 | goto out_drop; |
1079 | } | 1082 | } |
1080 | 1083 | ||
1081 | context->inode = inode; | 1084 | context->inode = inode; |
1082 | context->file = filp; | 1085 | context->file = filp; |
1083 | 1086 | ||
1084 | if (argp) { | 1087 | if (copy_from_user(&range, argp, sizeof(range))) { |
1085 | if (copy_from_user(&range, argp, sizeof(range))) { | 1088 | status = -EFAULT; |
1086 | status = -EFAULT; | 1089 | goto out_free; |
1087 | goto out; | ||
1088 | } | ||
1089 | } else { | ||
1090 | status = -EINVAL; | ||
1091 | goto out; | ||
1092 | } | 1090 | } |
1093 | 1091 | ||
1094 | if (range.me_start > i_size_read(inode)) | 1092 | if (range.me_start > i_size_read(inode)) |
1095 | goto out; | 1093 | goto out_free; |
1096 | 1094 | ||
1097 | if (range.me_start + range.me_len > i_size_read(inode)) | 1095 | if (range.me_start + range.me_len > i_size_read(inode)) |
1098 | range.me_len = i_size_read(inode) - range.me_start; | 1096 | range.me_len = i_size_read(inode) - range.me_start; |
@@ -1124,25 +1122,24 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp) | |||
1124 | 1122 | ||
1125 | status = ocfs2_validate_and_adjust_move_goal(inode, &range); | 1123 | status = ocfs2_validate_and_adjust_move_goal(inode, &range); |
1126 | if (status) | 1124 | if (status) |
1127 | goto out; | 1125 | goto out_copy; |
1128 | } | 1126 | } |
1129 | 1127 | ||
1130 | status = ocfs2_move_extents(context); | 1128 | status = ocfs2_move_extents(context); |
1131 | if (status) | 1129 | if (status) |
1132 | mlog_errno(status); | 1130 | mlog_errno(status); |
1133 | out: | 1131 | out_copy: |
1134 | /* | 1132 | /* |
1135 | * movement/defragmentation may end up being partially completed, | 1133 | * movement/defragmentation may end up being partially completed, |
1136 | * that's the reason why we need to return userspace the finished | 1134 | * that's the reason why we need to return userspace the finished |
1137 | * length and new_offset even if failure happens somewhere. | 1135 | * length and new_offset even if failure happens somewhere. |
1138 | */ | 1136 | */ |
1139 | if (argp) { | 1137 | if (copy_to_user(argp, &range, sizeof(range))) |
1140 | if (copy_to_user(argp, &range, sizeof(range))) | 1138 | status = -EFAULT; |
1141 | status = -EFAULT; | ||
1142 | } | ||
1143 | 1139 | ||
1140 | out_free: | ||
1144 | kfree(context); | 1141 | kfree(context); |
1145 | 1142 | out_drop: | |
1146 | mnt_drop_write_file(filp); | 1143 | mnt_drop_write_file(filp); |
1147 | 1144 | ||
1148 | return status; | 1145 | return status; |