aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/devpts/inode.c100
1 files changed, 22 insertions, 78 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index fb4da9d89130..70013dd8ec70 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -322,60 +322,21 @@ static int compare_init_pts_sb(struct super_block *s, void *p)
322} 322}
323 323
324/* 324/*
325 * Safely parse the mount options in @data and update @opts.
326 *
327 * devpts ends up parsing options two times during mount, due to the
328 * two modes of operation it supports. The first parse occurs in
329 * devpts_get_sb() when determining the mode (single-instance or
330 * multi-instance mode). The second parse happens in devpts_remount()
331 * or new_pts_mount() depending on the mode.
332 *
333 * Parsing of options modifies the @data making subsequent parsing
334 * incorrect. So make a local copy of @data and parse it.
335 *
336 * Return: 0 On success, -errno on error
337 */
338static int safe_parse_mount_options(void *data, struct pts_mount_opts *opts)
339{
340 int rc;
341 void *datacp;
342
343 if (!data)
344 return 0;
345
346 /* Use kstrdup() ? */
347 datacp = kmalloc(PAGE_SIZE, GFP_KERNEL);
348 if (!datacp)
349 return -ENOMEM;
350
351 memcpy(datacp, data, PAGE_SIZE);
352 rc = parse_mount_options((char *)datacp, PARSE_MOUNT, opts);
353 kfree(datacp);
354
355 return rc;
356}
357
358/*
359 * Mount a new (private) instance of devpts. PTYs created in this 325 * Mount a new (private) instance of devpts. PTYs created in this
360 * instance are independent of the PTYs in other devpts instances. 326 * instance are independent of the PTYs in other devpts instances.
361 */ 327 */
362static int new_pts_mount(struct file_system_type *fs_type, int flags, 328static int new_pts_mount(struct file_system_type *fs_type, int flags,
363 void *data, struct vfsmount *mnt) 329 void *data, struct pts_mount_opts *opts, struct vfsmount *mnt)
364{ 330{
365 int err; 331 int err;
366 struct pts_fs_info *fsi; 332 struct pts_fs_info *fsi;
367 struct pts_mount_opts *opts;
368 333
369 err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt); 334 err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt);
370 if (err) 335 if (err)
371 return err; 336 return err;
372 337
373 fsi = DEVPTS_SB(mnt->mnt_sb); 338 fsi = DEVPTS_SB(mnt->mnt_sb);
374 opts = &fsi->mount_opts; 339 memcpy(&fsi->mount_opts, opts, sizeof(opts));
375
376 err = parse_mount_options(data, PARSE_MOUNT, opts);
377 if (err)
378 goto fail;
379 340
380 err = mknod_ptmx(mnt->mnt_sb); 341 err = mknod_ptmx(mnt->mnt_sb);
381 if (err) 342 if (err)
@@ -391,28 +352,6 @@ fail:
391} 352}
392 353
393/* 354/*
394 * Check if 'newinstance' mount option was specified in @data.
395 *
396 * Return: -errno on error (eg: invalid mount options specified)
397 * : 1 if 'newinstance' mount option was specified
398 * : 0 if 'newinstance' mount option was NOT specified
399 */
400static int is_new_instance_mount(void *data)
401{
402 int rc;
403 struct pts_mount_opts opts;
404
405 if (!data)
406 return 0;
407
408 rc = safe_parse_mount_options(data, &opts);
409 if (!rc)
410 rc = opts.newinstance;
411
412 return rc;
413}
414
415/*
416 * get_init_pts_sb() 355 * get_init_pts_sb()
417 * 356 *
418 * This interface is needed to support multiple namespace semantics in 357 * This interface is needed to support multiple namespace semantics in
@@ -434,10 +373,9 @@ static int is_new_instance_mount(void *data)
434 * presence of the private namespace (i.e 'newinstance') super-blocks. 373 * presence of the private namespace (i.e 'newinstance') super-blocks.
435 */ 374 */
436static int get_init_pts_sb(struct file_system_type *fs_type, int flags, 375static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
437 void *data, struct vfsmount *mnt) 376 void *data, struct pts_mount_opts *opts, struct vfsmount *mnt)
438{ 377{
439 struct super_block *s; 378 struct super_block *s;
440 struct pts_mount_opts *opts;
441 struct pts_fs_info *fsi; 379 struct pts_fs_info *fsi;
442 int error; 380 int error;
443 381
@@ -455,11 +393,12 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
455 } 393 }
456 s->s_flags |= MS_ACTIVE; 394 s->s_flags |= MS_ACTIVE;
457 } 395 }
458 fsi = DEVPTS_SB(s);
459 opts = &fsi->mount_opts;
460 parse_mount_options(data, PARSE_REMOUNT, opts);
461 396
462 simple_set_mnt(mnt, s); 397 simple_set_mnt(mnt, s);
398
399 fsi = DEVPTS_SB(mnt->mnt_sb);
400 memcpy(&fsi->mount_opts, opts, sizeof(opts));
401
463 return 0; 402 return 0;
464} 403}
465 404
@@ -469,11 +408,11 @@ static int get_init_pts_sb(struct file_system_type *fs_type, int flags,
469 * kernel still allows multiple-instances. 408 * kernel still allows multiple-instances.
470 */ 409 */
471static int init_pts_mount(struct file_system_type *fs_type, int flags, 410static int init_pts_mount(struct file_system_type *fs_type, int flags,
472 void *data, struct vfsmount *mnt) 411 void *data, struct pts_mount_opts *opts, struct vfsmount *mnt)
473{ 412{
474 int err; 413 int err;
475 414
476 err = get_init_pts_sb(fs_type, flags, data, mnt); 415 err = get_init_pts_sb(fs_type, flags, data, opts, mnt);
477 if (err) 416 if (err)
478 return err; 417 return err;
479 418
@@ -490,17 +429,22 @@ static int init_pts_mount(struct file_system_type *fs_type, int flags,
490static int devpts_get_sb(struct file_system_type *fs_type, 429static int devpts_get_sb(struct file_system_type *fs_type,
491 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 430 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
492{ 431{
493 int new; 432 int error;
494 433 struct pts_mount_opts opts;
495 new = is_new_instance_mount(data);
496 if (new < 0)
497 return new;
498 434
499 if (new) 435 memset(&opts, 0, sizeof(opts));
500 return new_pts_mount(fs_type, flags, data, mnt); 436 if (data) {
437 error = parse_mount_options(data, PARSE_MOUNT, &opts);
438 if (error)
439 return error;
440 }
501 441
502 return init_pts_mount(fs_type, flags, data, mnt); 442 if (opts.newinstance)
443 return new_pts_mount(fs_type, flags, data, &opts, mnt);
444 else
445 return init_pts_mount(fs_type, flags, data, &opts, mnt);
503} 446}
447
504#else 448#else
505/* 449/*
506 * This supports only the legacy single-instance semantics (no 450 * This supports only the legacy single-instance semantics (no