diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-19 12:17:29 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-26 21:08:52 -0400 |
commit | 5b249b1b07c42c61d0c53b8ab4fad026e39a9be9 (patch) | |
tree | 671b511c34bcae46b69dface3122f08d0ac399bf | |
parent | a79f41ed9786b75ebe75e52295ad54049b8551b6 (diff) |
pipe(2) - race-free error recovery
don't mess with sys_close() if copy_to_user() fails; just postpone
fd_install() until we know it hasn't.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/pipe.c | 31 |
1 files changed, 22 insertions, 9 deletions
@@ -1064,9 +1064,8 @@ err_inode: | |||
1064 | return err; | 1064 | return err; |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | int do_pipe_flags(int *fd, int flags) | 1067 | static int __do_pipe_flags(int *fd, struct file **files, int flags) |
1068 | { | 1068 | { |
1069 | struct file *files[2]; | ||
1070 | int error; | 1069 | int error; |
1071 | int fdw, fdr; | 1070 | int fdw, fdr; |
1072 | 1071 | ||
@@ -1088,11 +1087,8 @@ int do_pipe_flags(int *fd, int flags) | |||
1088 | fdw = error; | 1087 | fdw = error; |
1089 | 1088 | ||
1090 | audit_fd_pair(fdr, fdw); | 1089 | audit_fd_pair(fdr, fdw); |
1091 | fd_install(fdr, files[0]); | ||
1092 | fd_install(fdw, files[1]); | ||
1093 | fd[0] = fdr; | 1090 | fd[0] = fdr; |
1094 | fd[1] = fdw; | 1091 | fd[1] = fdw; |
1095 | |||
1096 | return 0; | 1092 | return 0; |
1097 | 1093 | ||
1098 | err_fdr: | 1094 | err_fdr: |
@@ -1103,21 +1099,38 @@ int do_pipe_flags(int *fd, int flags) | |||
1103 | return error; | 1099 | return error; |
1104 | } | 1100 | } |
1105 | 1101 | ||
1102 | int do_pipe_flags(int *fd, int flags) | ||
1103 | { | ||
1104 | struct file *files[2]; | ||
1105 | int error = __do_pipe_flags(fd, files, flags); | ||
1106 | if (!error) { | ||
1107 | fd_install(fd[0], files[0]); | ||
1108 | fd_install(fd[1], files[1]); | ||
1109 | } | ||
1110 | return error; | ||
1111 | } | ||
1112 | |||
1106 | /* | 1113 | /* |
1107 | * sys_pipe() is the normal C calling standard for creating | 1114 | * sys_pipe() is the normal C calling standard for creating |
1108 | * a pipe. It's not the way Unix traditionally does this, though. | 1115 | * a pipe. It's not the way Unix traditionally does this, though. |
1109 | */ | 1116 | */ |
1110 | SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags) | 1117 | SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags) |
1111 | { | 1118 | { |
1119 | struct file *files[2]; | ||
1112 | int fd[2]; | 1120 | int fd[2]; |
1113 | int error; | 1121 | int error; |
1114 | 1122 | ||
1115 | error = do_pipe_flags(fd, flags); | 1123 | error = __do_pipe_flags(fd, files, flags); |
1116 | if (!error) { | 1124 | if (!error) { |
1117 | if (copy_to_user(fildes, fd, sizeof(fd))) { | 1125 | if (unlikely(copy_to_user(fildes, fd, sizeof(fd)))) { |
1118 | sys_close(fd[0]); | 1126 | fput(files[0]); |
1119 | sys_close(fd[1]); | 1127 | fput(files[1]); |
1128 | put_unused_fd(fd[0]); | ||
1129 | put_unused_fd(fd[1]); | ||
1120 | error = -EFAULT; | 1130 | error = -EFAULT; |
1131 | } else { | ||
1132 | fd_install(fd[0], files[0]); | ||
1133 | fd_install(fd[1], files[1]); | ||
1121 | } | 1134 | } |
1122 | } | 1135 | } |
1123 | return error; | 1136 | return error; |