aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-10 13:23:43 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-10 13:25:27 -0500
commit5a22e30def8b9539576ff047adb14455ca559f07 (patch)
treee1e76efd73b28e7ae8124383c263fcf92bcc11e0 /fs
parent19e00f2f1d5273dbc52eab0ebc315cae3aa44b2a (diff)
parent418a936e84e8f346da322c2e839992aa9df108d4 (diff)
Merge tag 'tty-3.3-rc3' tty-next
This is needed to handle the 8250 file merge mess properly for future patches. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/devpts/inode.c85
1 files changed, 81 insertions, 4 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index c4e2a58a2e82..1c6f908e38ca 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -36,7 +36,61 @@
36#define DEVPTS_DEFAULT_PTMX_MODE 0000 36#define DEVPTS_DEFAULT_PTMX_MODE 0000
37#define PTMX_MINOR 2 37#define PTMX_MINOR 2
38 38
39extern int pty_limit; /* Config limit on Unix98 ptys */ 39/*
40 * sysctl support for setting limits on the number of Unix98 ptys allocated.
41 * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
42 */
43static int pty_limit = NR_UNIX98_PTY_DEFAULT;
44static int pty_reserve = NR_UNIX98_PTY_RESERVE;
45static int pty_limit_min;
46static int pty_limit_max = INT_MAX;
47static int pty_count;
48
49static struct ctl_table pty_table[] = {
50 {
51 .procname = "max",
52 .maxlen = sizeof(int),
53 .mode = 0644,
54 .data = &pty_limit,
55 .proc_handler = proc_dointvec_minmax,
56 .extra1 = &pty_limit_min,
57 .extra2 = &pty_limit_max,
58 }, {
59 .procname = "reserve",
60 .maxlen = sizeof(int),
61 .mode = 0644,
62 .data = &pty_reserve,
63 .proc_handler = proc_dointvec_minmax,
64 .extra1 = &pty_limit_min,
65 .extra2 = &pty_limit_max,
66 }, {
67 .procname = "nr",
68 .maxlen = sizeof(int),
69 .mode = 0444,
70 .data = &pty_count,
71 .proc_handler = proc_dointvec,
72 },
73 {}
74};
75
76static struct ctl_table pty_kern_table[] = {
77 {
78 .procname = "pty",
79 .mode = 0555,
80 .child = pty_table,
81 },
82 {}
83};
84
85static struct ctl_table pty_root_table[] = {
86 {
87 .procname = "kernel",
88 .mode = 0555,
89 .child = pty_kern_table,
90 },
91 {}
92};
93
40static DEFINE_MUTEX(allocated_ptys_lock); 94static DEFINE_MUTEX(allocated_ptys_lock);
41 95
42static struct vfsmount *devpts_mnt; 96static struct vfsmount *devpts_mnt;
@@ -49,10 +103,11 @@ struct pts_mount_opts {
49 umode_t mode; 103 umode_t mode;
50 umode_t ptmxmode; 104 umode_t ptmxmode;
51 int newinstance; 105 int newinstance;
106 int max;
52}; 107};
53 108
54enum { 109enum {
55 Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, 110 Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max,
56 Opt_err 111 Opt_err
57}; 112};
58 113
@@ -63,6 +118,7 @@ static const match_table_t tokens = {
63#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES 118#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
64 {Opt_ptmxmode, "ptmxmode=%o"}, 119 {Opt_ptmxmode, "ptmxmode=%o"},
65 {Opt_newinstance, "newinstance"}, 120 {Opt_newinstance, "newinstance"},
121 {Opt_max, "max=%d"},
66#endif 122#endif
67 {Opt_err, NULL} 123 {Opt_err, NULL}
68}; 124};
@@ -109,6 +165,7 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
109 opts->gid = 0; 165 opts->gid = 0;
110 opts->mode = DEVPTS_DEFAULT_MODE; 166 opts->mode = DEVPTS_DEFAULT_MODE;
111 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; 167 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
168 opts->max = NR_UNIX98_PTY_MAX;
112 169
113 /* newinstance makes sense only on initial mount */ 170 /* newinstance makes sense only on initial mount */
114 if (op == PARSE_MOUNT) 171 if (op == PARSE_MOUNT)
@@ -152,6 +209,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
152 if (op == PARSE_MOUNT) 209 if (op == PARSE_MOUNT)
153 opts->newinstance = 1; 210 opts->newinstance = 1;
154 break; 211 break;
212 case Opt_max:
213 if (match_int(&args[0], &option) ||
214 option < 0 || option > NR_UNIX98_PTY_MAX)
215 return -EINVAL;
216 opts->max = option;
217 break;
155#endif 218#endif
156 default: 219 default:
157 printk(KERN_ERR "devpts: called with bogus options\n"); 220 printk(KERN_ERR "devpts: called with bogus options\n");
@@ -258,6 +321,8 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root)
258 seq_printf(seq, ",mode=%03o", opts->mode); 321 seq_printf(seq, ",mode=%03o", opts->mode);
259#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES 322#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
260 seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); 323 seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
324 if (opts->max < NR_UNIX98_PTY_MAX)
325 seq_printf(seq, ",max=%d", opts->max);
261#endif 326#endif
262 327
263 return 0; 328 return 0;
@@ -438,6 +503,12 @@ retry:
438 return -ENOMEM; 503 return -ENOMEM;
439 504
440 mutex_lock(&allocated_ptys_lock); 505 mutex_lock(&allocated_ptys_lock);
506 if (pty_count >= pty_limit -
507 (fsi->mount_opts.newinstance ? pty_reserve : 0)) {
508 mutex_unlock(&allocated_ptys_lock);
509 return -ENOSPC;
510 }
511
441 ida_ret = ida_get_new(&fsi->allocated_ptys, &index); 512 ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
442 if (ida_ret < 0) { 513 if (ida_ret < 0) {
443 mutex_unlock(&allocated_ptys_lock); 514 mutex_unlock(&allocated_ptys_lock);
@@ -446,11 +517,12 @@ retry:
446 return -EIO; 517 return -EIO;
447 } 518 }
448 519
449 if (index >= pty_limit) { 520 if (index >= fsi->mount_opts.max) {
450 ida_remove(&fsi->allocated_ptys, index); 521 ida_remove(&fsi->allocated_ptys, index);
451 mutex_unlock(&allocated_ptys_lock); 522 mutex_unlock(&allocated_ptys_lock);
452 return -EIO; 523 return -ENOSPC;
453 } 524 }
525 pty_count++;
454 mutex_unlock(&allocated_ptys_lock); 526 mutex_unlock(&allocated_ptys_lock);
455 return index; 527 return index;
456} 528}
@@ -462,6 +534,7 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
462 534
463 mutex_lock(&allocated_ptys_lock); 535 mutex_lock(&allocated_ptys_lock);
464 ida_remove(&fsi->allocated_ptys, idx); 536 ida_remove(&fsi->allocated_ptys, idx);
537 pty_count--;
465 mutex_unlock(&allocated_ptys_lock); 538 mutex_unlock(&allocated_ptys_lock);
466} 539}
467 540
@@ -558,11 +631,15 @@ void devpts_pty_kill(struct tty_struct *tty)
558static int __init init_devpts_fs(void) 631static int __init init_devpts_fs(void)
559{ 632{
560 int err = register_filesystem(&devpts_fs_type); 633 int err = register_filesystem(&devpts_fs_type);
634 struct ctl_table_header *table;
635
561 if (!err) { 636 if (!err) {
637 table = register_sysctl_table(pty_root_table);
562 devpts_mnt = kern_mount(&devpts_fs_type); 638 devpts_mnt = kern_mount(&devpts_fs_type);
563 if (IS_ERR(devpts_mnt)) { 639 if (IS_ERR(devpts_mnt)) {
564 err = PTR_ERR(devpts_mnt); 640 err = PTR_ERR(devpts_mnt);
565 unregister_filesystem(&devpts_fs_type); 641 unregister_filesystem(&devpts_fs_type);
642 unregister_sysctl_table(table);
566 } 643 }
567 } 644 }
568 return err; 645 return err;