aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-21 00:26:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-21 00:26:15 -0400
commit3aa2fc1667acdd9cca816a2bc9529f494bd61b05 (patch)
tree2379f33e47edacbc7a4bdf19607642d9c53caa11 /fs/kernfs/file.c
parent5af2344013454640e0133bb62e8cf2e30190a472 (diff)
parentc6e360a0d9d282e9c8688dcdabdc3669912b66ef (diff)
Merge tag 'driver-core-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH: "Here's the "big" driver core update for 4.7-rc1. Mostly just debugfs changes, the long-known and messy races with removing debugfs files should be fixed thanks to the great work of Nicolai Stange. We also have some isa updates in here (the x86 maintainers told me to take it through this tree), a new warning when we run out of dynamic char major numbers, and a few other assorted changes, details in the shortlog. All have been in linux-next for some time with no reported issues" * tag 'driver-core-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (32 commits) Revert "base: dd: don't remove driver_data in -EPROBE_DEFER case" gpio: ws16c48: Utilize the ISA bus driver gpio: 104-idio-16: Utilize the ISA bus driver gpio: 104-idi-48: Utilize the ISA bus driver gpio: 104-dio-48e: Utilize the ISA bus driver watchdog: ebc-c384_wdt: Utilize the ISA bus driver iio: stx104: Utilize the module_isa_driver and max_num_isa_dev macros iio: stx104: Add X86 dependency to STX104 Kconfig option Documentation: Add ISA bus driver documentation isa: Implement the max_num_isa_dev macro isa: Implement the module_isa_driver macro pnp: pnpbios: Add explicit X86_32 dependency to PNPBIOS isa: Decouple X86_32 dependency from the ISA Kconfig option driver-core: use 'dev' argument in dev_dbg_ratelimited stub base: dd: don't remove driver_data in -EPROBE_DEFER case kernfs: Move faulting copy_user operations outside of the mutex devcoredump: add scatterlist support debugfs: unproxify files created through debugfs_create_u32_array() debugfs: unproxify files created through debugfs_create_blob() debugfs: unproxify files created through debugfs_create_bool() ...
Diffstat (limited to 'fs/kernfs/file.c')
-rw-r--r--fs/kernfs/file.c51
1 files changed, 29 insertions, 22 deletions
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 7247252ee9b1..e1574008adc9 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -190,15 +190,16 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
190 char *buf; 190 char *buf;
191 191
192 buf = of->prealloc_buf; 192 buf = of->prealloc_buf;
193 if (!buf) 193 if (buf)
194 mutex_lock(&of->prealloc_mutex);
195 else
194 buf = kmalloc(len, GFP_KERNEL); 196 buf = kmalloc(len, GFP_KERNEL);
195 if (!buf) 197 if (!buf)
196 return -ENOMEM; 198 return -ENOMEM;
197 199
198 /* 200 /*
199 * @of->mutex nests outside active ref and is used both to ensure that 201 * @of->mutex nests outside active ref and is used both to ensure that
200 * the ops aren't called concurrently for the same open file, and 202 * the ops aren't called concurrently for the same open file.
201 * to provide exclusive access to ->prealloc_buf (when that exists).
202 */ 203 */
203 mutex_lock(&of->mutex); 204 mutex_lock(&of->mutex);
204 if (!kernfs_get_active(of->kn)) { 205 if (!kernfs_get_active(of->kn)) {
@@ -214,21 +215,23 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
214 else 215 else
215 len = -EINVAL; 216 len = -EINVAL;
216 217
218 kernfs_put_active(of->kn);
219 mutex_unlock(&of->mutex);
220
217 if (len < 0) 221 if (len < 0)
218 goto out_unlock; 222 goto out_free;
219 223
220 if (copy_to_user(user_buf, buf, len)) { 224 if (copy_to_user(user_buf, buf, len)) {
221 len = -EFAULT; 225 len = -EFAULT;
222 goto out_unlock; 226 goto out_free;
223 } 227 }
224 228
225 *ppos += len; 229 *ppos += len;
226 230
227 out_unlock:
228 kernfs_put_active(of->kn);
229 mutex_unlock(&of->mutex);
230 out_free: 231 out_free:
231 if (buf != of->prealloc_buf) 232 if (buf == of->prealloc_buf)
233 mutex_unlock(&of->prealloc_mutex);
234 else
232 kfree(buf); 235 kfree(buf);
233 return len; 236 return len;
234} 237}
@@ -284,15 +287,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
284 } 287 }
285 288
286 buf = of->prealloc_buf; 289 buf = of->prealloc_buf;
287 if (!buf) 290 if (buf)
291 mutex_lock(&of->prealloc_mutex);
292 else
288 buf = kmalloc(len + 1, GFP_KERNEL); 293 buf = kmalloc(len + 1, GFP_KERNEL);
289 if (!buf) 294 if (!buf)
290 return -ENOMEM; 295 return -ENOMEM;
291 296
297 if (copy_from_user(buf, user_buf, len)) {
298 len = -EFAULT;
299 goto out_free;
300 }
301 buf[len] = '\0'; /* guarantee string termination */
302
292 /* 303 /*
293 * @of->mutex nests outside active ref and is used both to ensure that 304 * @of->mutex nests outside active ref and is used both to ensure that
294 * the ops aren't called concurrently for the same open file, and 305 * the ops aren't called concurrently for the same open file.
295 * to provide exclusive access to ->prealloc_buf (when that exists).
296 */ 306 */
297 mutex_lock(&of->mutex); 307 mutex_lock(&of->mutex);
298 if (!kernfs_get_active(of->kn)) { 308 if (!kernfs_get_active(of->kn)) {
@@ -301,26 +311,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
301 goto out_free; 311 goto out_free;
302 } 312 }
303 313
304 if (copy_from_user(buf, user_buf, len)) {
305 len = -EFAULT;
306 goto out_unlock;
307 }
308 buf[len] = '\0'; /* guarantee string termination */
309
310 ops = kernfs_ops(of->kn); 314 ops = kernfs_ops(of->kn);
311 if (ops->write) 315 if (ops->write)
312 len = ops->write(of, buf, len, *ppos); 316 len = ops->write(of, buf, len, *ppos);
313 else 317 else
314 len = -EINVAL; 318 len = -EINVAL;
315 319
320 kernfs_put_active(of->kn);
321 mutex_unlock(&of->mutex);
322
316 if (len > 0) 323 if (len > 0)
317 *ppos += len; 324 *ppos += len;
318 325
319out_unlock:
320 kernfs_put_active(of->kn);
321 mutex_unlock(&of->mutex);
322out_free: 326out_free:
323 if (buf != of->prealloc_buf) 327 if (buf == of->prealloc_buf)
328 mutex_unlock(&of->prealloc_mutex);
329 else
324 kfree(buf); 330 kfree(buf);
325 return len; 331 return len;
326} 332}
@@ -687,6 +693,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
687 error = -ENOMEM; 693 error = -ENOMEM;
688 if (!of->prealloc_buf) 694 if (!of->prealloc_buf)
689 goto err_free; 695 goto err_free;
696 mutex_init(&of->prealloc_mutex);
690 } 697 }
691 698
692 /* 699 /*