configfs: fix the read and write iterators

Commit 7fe1e79b59ba ("configfs: implement the .read_iter and .write_iter
methods") changed the simple_read_from_buffer() calls into copy_to_iter()
calls and the simple_write_to_buffer() calls into copy_from_iter() calls.
The simple*buffer() methods update the file offset (*ppos) but the read
and write iterators not yet. Make the read and write iterators update the
file offset (iocb->ki_pos).

This patch has been tested as follows:

# modprobe target_core_user
# dd if=/sys/kernel/config/target/dbroot bs=1
/var/target
12+0 records in
12+0 records out
12 bytes copied, 9.5539e-05 s, 126 kB/s

# cd /sys/kernel/config/acpi/table
# mkdir test
# cd test
# dmesg -c >/dev/null; printf 'SSDT\x8\0\0\0abcdefghijklmnopqrstuvwxyz' | dd of=aml bs=1; dmesg -c
34+0 records in
34+0 records out
34 bytes copied, 0.010627 s, 3.2 kB/s
[ 261.056551] ACPI configfs: invalid table length

Reported-by: Yanko Kaneti <yaneti@declera.com>
Cc: Yanko Kaneti <yaneti@declera.com>
Fixes: 7fe1e79b59ba ("configfs: implement the .read_iter and .write_iter methods")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>

authored by Bart Van Assche and committed by Christoph Hellwig 420405ec 7fef2edf

+22 -7
+22 -7
fs/configfs/file.c
··· 91 91 } 92 92 pr_debug("%s: count = %zd, pos = %lld, buf = %s\n", 93 93 __func__, iov_iter_count(to), iocb->ki_pos, buffer->page); 94 - retval = copy_to_iter(buffer->page, buffer->count, to); 94 + if (iocb->ki_pos >= buffer->count) 95 + goto out; 96 + retval = copy_to_iter(buffer->page + iocb->ki_pos, 97 + buffer->count - iocb->ki_pos, to); 95 98 iocb->ki_pos += retval; 96 99 if (retval == 0) 97 100 retval = -EFAULT; ··· 165 162 buffer->needs_read_fill = 0; 166 163 } 167 164 168 - retval = copy_to_iter(buffer->bin_buffer, buffer->bin_buffer_size, to); 165 + if (iocb->ki_pos >= buffer->bin_buffer_size) 166 + goto out; 167 + retval = copy_to_iter(buffer->bin_buffer + iocb->ki_pos, 168 + buffer->bin_buffer_size - iocb->ki_pos, to); 169 169 iocb->ki_pos += retval; 170 170 if (retval == 0) 171 171 retval = -EFAULT; ··· 177 171 return retval; 178 172 } 179 173 180 - static int fill_write_buffer(struct configfs_buffer *buffer, 174 + /* Fill [buffer, buffer + pos) with data coming from @from. */ 175 + static int fill_write_buffer(struct configfs_buffer *buffer, loff_t pos, 181 176 struct iov_iter *from) 182 177 { 178 + loff_t to_copy; 183 179 int copied; 180 + u8 *to; 184 181 185 182 if (!buffer->page) 186 183 buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0); 187 184 if (!buffer->page) 188 185 return -ENOMEM; 189 186 190 - copied = copy_from_iter(buffer->page, SIMPLE_ATTR_SIZE - 1, from); 187 + to_copy = SIMPLE_ATTR_SIZE - 1 - pos; 188 + if (to_copy <= 0) 189 + return 0; 190 + to = buffer->page + pos; 191 + copied = copy_from_iter(to, to_copy, from); 191 192 buffer->needs_read_fill = 1; 192 193 /* if buf is assumed to contain a string, terminate it by \0, 193 194 * so e.g. sscanf() can scan the string easily */ 194 - buffer->page[copied] = 0; 195 + to[copied] = 0; 195 196 return copied ? : -EFAULT; 196 197 } 197 198 ··· 230 217 ssize_t len; 231 218 232 219 mutex_lock(&buffer->mutex); 233 - len = fill_write_buffer(buffer, from); 220 + len = fill_write_buffer(buffer, iocb->ki_pos, from); 234 221 if (len > 0) 235 222 len = flush_write_buffer(file, buffer, len); 236 223 if (len > 0) ··· 285 272 buffer->bin_buffer_size = end_offset; 286 273 } 287 274 288 - len = copy_from_iter(buffer->bin_buffer, buffer->bin_buffer_size, from); 275 + len = copy_from_iter(buffer->bin_buffer + iocb->ki_pos, 276 + buffer->bin_buffer_size - iocb->ki_pos, from); 277 + iocb->ki_pos += len; 289 278 out: 290 279 mutex_unlock(&buffer->mutex); 291 280 return len ? : -EFAULT;