aboutsummaryrefslogtreecommitdiffstats
path: root/fs/devpts/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/devpts/inode.c')
-rw-r--r--fs/devpts/inode.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index c2c7317d5687..1c6f908e38ca 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -41,8 +41,9 @@
41 * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. 41 * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
42 */ 42 */
43static int pty_limit = NR_UNIX98_PTY_DEFAULT; 43static int pty_limit = NR_UNIX98_PTY_DEFAULT;
44static int pty_reserve = NR_UNIX98_PTY_RESERVE;
44static int pty_limit_min; 45static int pty_limit_min;
45static int pty_limit_max = NR_UNIX98_PTY_MAX; 46static int pty_limit_max = INT_MAX;
46static int pty_count; 47static int pty_count;
47 48
48static struct ctl_table pty_table[] = { 49static struct ctl_table pty_table[] = {
@@ -55,6 +56,14 @@ static struct ctl_table pty_table[] = {
55 .extra1 = &pty_limit_min, 56 .extra1 = &pty_limit_min,
56 .extra2 = &pty_limit_max, 57 .extra2 = &pty_limit_max,
57 }, { 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 }, {
58 .procname = "nr", 67 .procname = "nr",
59 .maxlen = sizeof(int), 68 .maxlen = sizeof(int),
60 .mode = 0444, 69 .mode = 0444,
@@ -94,10 +103,11 @@ struct pts_mount_opts {
94 umode_t mode; 103 umode_t mode;
95 umode_t ptmxmode; 104 umode_t ptmxmode;
96 int newinstance; 105 int newinstance;
106 int max;
97}; 107};
98 108
99enum { 109enum {
100 Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, 110 Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max,
101 Opt_err 111 Opt_err
102}; 112};
103 113
@@ -108,6 +118,7 @@ static const match_table_t tokens = {
108#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES 118#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
109 {Opt_ptmxmode, "ptmxmode=%o"}, 119 {Opt_ptmxmode, "ptmxmode=%o"},
110 {Opt_newinstance, "newinstance"}, 120 {Opt_newinstance, "newinstance"},
121 {Opt_max, "max=%d"},
111#endif 122#endif
112 {Opt_err, NULL} 123 {Opt_err, NULL}
113}; 124};
@@ -154,6 +165,7 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
154 opts->gid = 0; 165 opts->gid = 0;
155 opts->mode = DEVPTS_DEFAULT_MODE; 166 opts->mode = DEVPTS_DEFAULT_MODE;
156 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; 167 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
168 opts->max = NR_UNIX98_PTY_MAX;
157 169
158 /* newinstance makes sense only on initial mount */ 170 /* newinstance makes sense only on initial mount */
159 if (op == PARSE_MOUNT) 171 if (op == PARSE_MOUNT)
@@ -197,6 +209,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
197 if (op == PARSE_MOUNT) 209 if (op == PARSE_MOUNT)
198 opts->newinstance = 1; 210 opts->newinstance = 1;
199 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;
200#endif 218#endif
201 default: 219 default:
202 printk(KERN_ERR "devpts: called with bogus options\n"); 220 printk(KERN_ERR "devpts: called with bogus options\n");
@@ -303,6 +321,8 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root)
303 seq_printf(seq, ",mode=%03o", opts->mode); 321 seq_printf(seq, ",mode=%03o", opts->mode);
304#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES 322#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
305 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);
306#endif 326#endif
307 327
308 return 0; 328 return 0;
@@ -483,6 +503,12 @@ retry:
483 return -ENOMEM; 503 return -ENOMEM;
484 504
485 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
486 ida_ret = ida_get_new(&fsi->allocated_ptys, &index); 512 ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
487 if (ida_ret < 0) { 513 if (ida_ret < 0) {
488 mutex_unlock(&allocated_ptys_lock); 514 mutex_unlock(&allocated_ptys_lock);
@@ -491,10 +517,10 @@ retry:
491 return -EIO; 517 return -EIO;
492 } 518 }
493 519
494 if (index >= pty_limit) { 520 if (index >= fsi->mount_opts.max) {
495 ida_remove(&fsi->allocated_ptys, index); 521 ida_remove(&fsi->allocated_ptys, index);
496 mutex_unlock(&allocated_ptys_lock); 522 mutex_unlock(&allocated_ptys_lock);
497 return -EIO; 523 return -ENOSPC;
498 } 524 }
499 pty_count++; 525 pty_count++;
500 mutex_unlock(&allocated_ptys_lock); 526 mutex_unlock(&allocated_ptys_lock);