Merge branch 'splice-2.6.23' of git://git.kernel.dk/data/git/linux-2.6-block

* 'splice-2.6.23' of git://git.kernel.dk/data/git/linux-2.6-block:
splice: fix offset mangling with direct splicing (sendfile)
security: revalidate rw permissions for sys_splice and sys_vmsplice
relay: fixup kerneldoc comment
relay: fix bogus cast in subbuf_splice_actor()

+24 -25
+20 -23
fs/splice.c
··· 28 28 #include <linux/module.h> 29 29 #include <linux/syscalls.h> 30 30 #include <linux/uio.h> 31 + #include <linux/security.h> 31 32 32 33 /* 33 34 * Attempt to steal a page from a pipe buffer. This should perhaps go into ··· 492 491 493 492 ret = 0; 494 493 spliced = 0; 495 - while (len) { 494 + while (len && !spliced) { 496 495 ret = __generic_file_splice_read(in, ppos, pipe, len, flags); 497 496 498 497 if (ret < 0) ··· 962 961 if (unlikely(ret < 0)) 963 962 return ret; 964 963 964 + ret = security_file_permission(out, MAY_WRITE); 965 + if (unlikely(ret < 0)) 966 + return ret; 967 + 965 968 return out->f_op->splice_write(pipe, out, ppos, len, flags); 966 969 } 967 970 ··· 985 980 return -EBADF; 986 981 987 982 ret = rw_verify_area(READ, in, ppos, len); 983 + if (unlikely(ret < 0)) 984 + return ret; 985 + 986 + ret = security_file_permission(in, MAY_READ); 988 987 if (unlikely(ret < 0)) 989 988 return ret; 990 989 ··· 1060 1051 sd->flags &= ~SPLICE_F_NONBLOCK; 1061 1052 1062 1053 while (len) { 1063 - size_t read_len, max_read_len; 1054 + size_t read_len; 1064 1055 1065 - /* 1066 - * Do at most PIPE_BUFFERS pages worth of transfer: 1067 - */ 1068 - max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); 1069 - 1070 - ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags); 1071 - if (unlikely(ret < 0)) 1056 + ret = do_splice_to(in, &sd->pos, pipe, len, flags); 1057 + if (unlikely(ret <= 0)) 1072 1058 goto out_release; 1073 1059 1074 1060 read_len = ret; ··· 1075 1071 * could get stuck data in the internal pipe: 1076 1072 */ 1077 1073 ret = actor(pipe, sd); 1078 - if (unlikely(ret < 0)) 1074 + if (unlikely(ret <= 0)) 1079 1075 goto out_release; 1080 1076 1081 1077 bytes += ret; 1082 1078 len -= ret; 1083 1079 1084 - /* 1085 - * In nonblocking mode, if we got back a short read then 1086 - * that was due to either an IO error or due to the 1087 - * pagecache entry not being there. In the IO error case 1088 - * the _next_ splice attempt will produce a clean IO error 1089 - * return value (not a short read), so in both cases it's 1090 - * correct to break out of the loop here: 1091 - */ 1092 - if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len)) 1093 - break; 1080 + if (ret < read_len) 1081 + goto out_release; 1094 1082 } 1095 1083 1096 1084 pipe->nrbufs = pipe->curbuf = 0; 1097 - 1098 1085 return bytes; 1099 1086 1100 1087 out_release: ··· 1147 1152 .pos = *ppos, 1148 1153 .u.file = out, 1149 1154 }; 1150 - size_t ret; 1155 + long ret; 1151 1156 1152 1157 ret = splice_direct_to_actor(in, &sd, direct_splice_actor); 1153 - *ppos = sd.pos; 1158 + if (ret > 0) 1159 + *ppos += ret; 1160 + 1154 1161 return ret; 1155 1162 } 1156 1163
+4 -2
kernel/relay.c
··· 1061 1061 .get = generic_pipe_buf_get, 1062 1062 }; 1063 1063 1064 - /** 1064 + /* 1065 1065 * subbuf_splice_actor - splice up to one subbuf's worth of data 1066 1066 */ 1067 1067 static int subbuf_splice_actor(struct file *in, ··· 1074 1074 unsigned int pidx, poff, total_len, subbuf_pages, ret; 1075 1075 struct rchan_buf *rbuf = in->private_data; 1076 1076 unsigned int subbuf_size = rbuf->chan->subbuf_size; 1077 - size_t read_start = ((size_t)*ppos) % rbuf->chan->alloc_size; 1077 + uint64_t pos = (uint64_t) *ppos; 1078 + uint32_t alloc_size = (uint32_t) rbuf->chan->alloc_size; 1079 + size_t read_start = (size_t) do_div(pos, alloc_size); 1078 1080 size_t read_subbuf = read_start / subbuf_size; 1079 1081 size_t padding = rbuf->padding[read_subbuf]; 1080 1082 size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;