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.c88
1 files changed, 82 insertions, 6 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index c4e2a58a2e82..10f5e0b484db 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;
@@ -309,12 +374,11 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
309 inode->i_fop = &simple_dir_operations; 374 inode->i_fop = &simple_dir_operations;
310 set_nlink(inode, 2); 375 set_nlink(inode, 2);
311 376
312 s->s_root = d_alloc_root(inode); 377 s->s_root = d_make_root(inode);
313 if (s->s_root) 378 if (s->s_root)
314 return 0; 379 return 0;
315 380
316 printk(KERN_ERR "devpts: get root dentry failed\n"); 381 printk(KERN_ERR "devpts: get root dentry failed\n");
317 iput(inode);
318 382
319fail: 383fail:
320 return -ENOMEM; 384 return -ENOMEM;
@@ -438,6 +502,12 @@ retry:
438 return -ENOMEM; 502 return -ENOMEM;
439 503
440 mutex_lock(&allocated_ptys_lock); 504 mutex_lock(&allocated_ptys_lock);
505 if (pty_count >= pty_limit -
506 (fsi->mount_opts.newinstance ? pty_reserve : 0)) {
507 mutex_unlock(&allocated_ptys_lock);
508 return -ENOSPC;
509 }
510
441 ida_ret = ida_get_new(&fsi->allocated_ptys, &index); 511 ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
442 if (ida_ret < 0) { 512 if (ida_ret < 0) {
443 mutex_unlock(&allocated_ptys_lock); 513 mutex_unlock(&allocated_ptys_lock);
@@ -446,11 +516,12 @@ retry:
446 return -EIO; 516 return -EIO;
447 } 517 }
448 518
449 if (index >= pty_limit) { 519 if (index >= fsi->mount_opts.max) {
450 ida_remove(&fsi->allocated_ptys, index); 520 ida_remove(&fsi->allocated_ptys, index);
451 mutex_unlock(&allocated_ptys_lock); 521 mutex_unlock(&allocated_ptys_lock);
452 return -EIO; 522 return -ENOSPC;
453 } 523 }
524 pty_count++;
454 mutex_unlock(&allocated_ptys_lock); 525 mutex_unlock(&allocated_ptys_lock);
455 return index; 526 return index;
456} 527}
@@ -462,6 +533,7 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
462 533
463 mutex_lock(&allocated_ptys_lock); 534 mutex_lock(&allocated_ptys_lock);
464 ida_remove(&fsi->allocated_ptys, idx); 535 ida_remove(&fsi->allocated_ptys, idx);
536 pty_count--;
465 mutex_unlock(&allocated_ptys_lock); 537 mutex_unlock(&allocated_ptys_lock);
466} 538}
467 539
@@ -558,11 +630,15 @@ void devpts_pty_kill(struct tty_struct *tty)
558static int __init init_devpts_fs(void) 630static int __init init_devpts_fs(void)
559{ 631{
560 int err = register_filesystem(&devpts_fs_type); 632 int err = register_filesystem(&devpts_fs_type);
633 struct ctl_table_header *table;
634
561 if (!err) { 635 if (!err) {
636 table = register_sysctl_table(pty_root_table);
562 devpts_mnt = kern_mount(&devpts_fs_type); 637 devpts_mnt = kern_mount(&devpts_fs_type);
563 if (IS_ERR(devpts_mnt)) { 638 if (IS_ERR(devpts_mnt)) {
564 err = PTR_ERR(devpts_mnt); 639 err = PTR_ERR(devpts_mnt);
565 unregister_filesystem(&devpts_fs_type); 640 unregister_filesystem(&devpts_fs_type);
641 unregister_sysctl_table(table);
566 } 642 }
567 } 643 }
568 return err; 644 return err;