1 |
dpavlin |
4 |
diff -rup linux-2.6.5.orig/fs/filesystems.c linux-2.6.5/fs/filesystems.c |
2 |
|
|
--- linux-2.6.5.orig/fs/filesystems.c 2003-12-18 03:59:18.000000000 +0100 |
3 |
|
|
+++ linux-2.6.5/fs/filesystems.c 2004-04-05 10:54:37.000000000 +0200 |
4 |
|
|
@@ -222,7 +222,8 @@ struct file_system_type *get_fs_type(con |
5 |
|
|
if (fs && !try_module_get(fs->owner)) |
6 |
|
|
fs = NULL; |
7 |
|
|
read_unlock(&file_systems_lock); |
8 |
|
|
- if (!fs && (request_module("%s", name) == 0)) { |
9 |
|
|
+ if (!fs && capable(CAP_SYS_ADMIN) && |
10 |
|
|
+ (request_module("%s", name) == 0)) { |
11 |
|
|
read_lock(&file_systems_lock); |
12 |
|
|
fs = *(find_filesystem(name)); |
13 |
|
|
if (fs && !try_module_get(fs->owner)) |
14 |
|
|
diff -rup linux-2.6.5.orig/fs/namespace.c linux-2.6.5/fs/namespace.c |
15 |
|
|
--- linux-2.6.5.orig/fs/namespace.c 2004-04-05 10:50:46.000000000 +0200 |
16 |
|
|
+++ linux-2.6.5/fs/namespace.c 2004-04-05 10:54:37.000000000 +0200 |
17 |
|
|
@@ -25,13 +25,16 @@ |
18 |
|
|
|
19 |
|
|
extern int __init init_rootfs(void); |
20 |
|
|
extern int __init sysfs_init(void); |
21 |
|
|
+extern void put_filesystem(struct file_system_type *fs); |
22 |
|
|
+ |
23 |
|
|
+#define MAX_MOUNTS 256 |
24 |
|
|
|
25 |
|
|
/* spinlock for vfsmount related operations, inplace of dcache_lock */ |
26 |
|
|
spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; |
27 |
|
|
static struct list_head *mount_hashtable; |
28 |
|
|
static int hash_mask, hash_bits; |
29 |
|
|
static kmem_cache_t *mnt_cache; |
30 |
|
|
- |
31 |
|
|
+struct mounts_stat_struct mounts_stat = { .max_mounts = MAX_MOUNTS }; |
32 |
|
|
static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) |
33 |
|
|
{ |
34 |
|
|
unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES); |
35 |
|
|
@@ -40,10 +43,38 @@ static inline unsigned long hash(struct |
36 |
|
|
return tmp & hash_mask; |
37 |
|
|
} |
38 |
|
|
|
39 |
|
|
+static inline int inc_nr_mounts(void) |
40 |
|
|
+{ |
41 |
|
|
+ int err = 0; |
42 |
|
|
+ spin_lock(&vfsmount_lock); |
43 |
|
|
+ if (capable(CAP_SYS_ADMIN) || |
44 |
|
|
+ mounts_stat.nr_mounts < mounts_stat.max_mounts) |
45 |
|
|
+ mounts_stat.nr_mounts++; |
46 |
|
|
+ else |
47 |
|
|
+ err = mounts_stat.max_mounts ? -EMFILE : -EPERM; |
48 |
|
|
+ spin_unlock(&vfsmount_lock); |
49 |
|
|
+ return err; |
50 |
|
|
+} |
51 |
|
|
+ |
52 |
|
|
+static inline void dec_nr_mounts(void) |
53 |
|
|
+{ |
54 |
|
|
+ spin_lock(&vfsmount_lock); |
55 |
|
|
+ mounts_stat.nr_mounts--; |
56 |
|
|
+ spin_unlock(&vfsmount_lock); |
57 |
|
|
+} |
58 |
|
|
+ |
59 |
|
|
struct vfsmount *alloc_vfsmnt(const char *name) |
60 |
|
|
{ |
61 |
|
|
- struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); |
62 |
|
|
- if (mnt) { |
63 |
|
|
+ struct vfsmount *mnt; |
64 |
|
|
+ int err = inc_nr_mounts(); |
65 |
|
|
+ if (err) |
66 |
|
|
+ return ERR_PTR(err); |
67 |
|
|
+ |
68 |
|
|
+ mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); |
69 |
|
|
+ if (!mnt) { |
70 |
|
|
+ dec_nr_mounts(); |
71 |
|
|
+ return ERR_PTR(-ENOMEM); |
72 |
|
|
+ } else { |
73 |
|
|
memset(mnt, 0, sizeof(struct vfsmount)); |
74 |
|
|
atomic_set(&mnt->mnt_count,1); |
75 |
|
|
INIT_LIST_HEAD(&mnt->mnt_hash); |
76 |
|
|
@@ -66,6 +97,7 @@ void free_vfsmnt(struct vfsmount *mnt) |
77 |
|
|
{ |
78 |
|
|
kfree(mnt->mnt_devname); |
79 |
|
|
kmem_cache_free(mnt_cache, mnt); |
80 |
|
|
+ dec_nr_mounts(); |
81 |
|
|
} |
82 |
|
|
|
83 |
|
|
/* |
84 |
|
|
@@ -147,13 +179,14 @@ clone_mnt(struct vfsmount *old, struct d |
85 |
|
|
struct super_block *sb = old->mnt_sb; |
86 |
|
|
struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname); |
87 |
|
|
|
88 |
|
|
- if (mnt) { |
89 |
|
|
+ if (!IS_ERR(mnt)) { |
90 |
|
|
mnt->mnt_flags = old->mnt_flags; |
91 |
|
|
atomic_inc(&sb->s_active); |
92 |
|
|
mnt->mnt_sb = sb; |
93 |
|
|
mnt->mnt_root = dget(root); |
94 |
|
|
mnt->mnt_mountpoint = mnt->mnt_root; |
95 |
|
|
mnt->mnt_parent = mnt; |
96 |
|
|
+ mnt->user = capable(CAP_SYS_ADMIN) ? 0 : current->fsuid; |
97 |
|
|
} |
98 |
|
|
return mnt; |
99 |
|
|
} |
100 |
|
|
@@ -238,6 +271,8 @@ static int show_vfsmnt(struct seq_file * |
101 |
|
|
if (mnt->mnt_flags & fs_infop->flag) |
102 |
|
|
seq_puts(m, fs_infop->str); |
103 |
|
|
} |
104 |
|
|
+ if (mnt->user) |
105 |
|
|
+ seq_printf(m, ",user=%i", mnt->user); |
106 |
|
|
if (mnt->mnt_sb->s_op->show_options) |
107 |
|
|
err = mnt->mnt_sb->s_op->show_options(m, mnt); |
108 |
|
|
seq_puts(m, " 0 0\n"); |
109 |
|
|
@@ -388,8 +423,10 @@ asmlinkage long sys_umount(char __user * |
110 |
|
|
goto dput_and_out; |
111 |
|
|
|
112 |
|
|
retval = -EPERM; |
113 |
|
|
- if (!capable(CAP_SYS_ADMIN)) |
114 |
|
|
- goto dput_and_out; |
115 |
|
|
+ if (!capable(CAP_SYS_ADMIN)) { |
116 |
|
|
+ if(nd.mnt->user != current->fsuid || (flags & MNT_FORCE)) |
117 |
|
|
+ goto dput_and_out; |
118 |
|
|
+ } |
119 |
|
|
|
120 |
|
|
retval = do_umount(nd.mnt, flags); |
121 |
|
|
dput_and_out: |
122 |
|
|
@@ -409,20 +446,15 @@ asmlinkage long sys_oldumount(char __use |
123 |
|
|
|
124 |
|
|
static int mount_is_safe(struct nameidata *nd) |
125 |
|
|
{ |
126 |
|
|
- if (capable(CAP_SYS_ADMIN)) |
127 |
|
|
- return 0; |
128 |
|
|
- return -EPERM; |
129 |
|
|
-#ifdef notyet |
130 |
|
|
- if (S_ISLNK(nd->dentry->d_inode->i_mode)) |
131 |
|
|
- return -EPERM; |
132 |
|
|
- if (nd->dentry->d_inode->i_mode & S_ISVTX) { |
133 |
|
|
- if (current->uid != nd->dentry->d_inode->i_uid) |
134 |
|
|
+ if (!capable(CAP_SYS_ADMIN)) { |
135 |
|
|
+ if (!S_ISDIR(nd->dentry->d_inode->i_mode) && |
136 |
|
|
+ !S_ISREG(nd->dentry->d_inode->i_mode)) |
137 |
|
|
+ return -EPERM; |
138 |
|
|
+ if (current->fsuid != nd->dentry->d_inode->i_uid || |
139 |
|
|
+ permission(nd->dentry->d_inode, MAY_WRITE, nd)) |
140 |
|
|
return -EPERM; |
141 |
|
|
} |
142 |
|
|
- if (permission(nd->dentry->d_inode, MAY_WRITE, nd)) |
143 |
|
|
- return -EPERM; |
144 |
|
|
return 0; |
145 |
|
|
-#endif |
146 |
|
|
} |
147 |
|
|
|
148 |
|
|
static int |
149 |
|
|
@@ -444,8 +476,8 @@ static struct vfsmount *copy_tree(struct |
150 |
|
|
struct nameidata nd; |
151 |
|
|
|
152 |
|
|
res = q = clone_mnt(mnt, dentry); |
153 |
|
|
- if (!q) |
154 |
|
|
- goto Enomem; |
155 |
|
|
+ if (IS_ERR(q)) |
156 |
|
|
+ goto out_error; |
157 |
|
|
q->mnt_mountpoint = mnt->mnt_mountpoint; |
158 |
|
|
|
159 |
|
|
p = mnt; |
160 |
|
|
@@ -463,8 +495,8 @@ static struct vfsmount *copy_tree(struct |
161 |
|
|
nd.mnt = q; |
162 |
|
|
nd.dentry = p->mnt_mountpoint; |
163 |
|
|
q = clone_mnt(p, p->mnt_root); |
164 |
|
|
- if (!q) |
165 |
|
|
- goto Enomem; |
166 |
|
|
+ if (IS_ERR(q)) |
167 |
|
|
+ goto out_error; |
168 |
|
|
spin_lock(&vfsmount_lock); |
169 |
|
|
list_add_tail(&q->mnt_list, &res->mnt_list); |
170 |
|
|
attach_mnt(q, &nd); |
171 |
|
|
@@ -472,13 +504,13 @@ static struct vfsmount *copy_tree(struct |
172 |
|
|
} |
173 |
|
|
} |
174 |
|
|
return res; |
175 |
|
|
- Enomem: |
176 |
|
|
+ out_error: |
177 |
|
|
if (res) { |
178 |
|
|
spin_lock(&vfsmount_lock); |
179 |
|
|
umount_tree(res); |
180 |
|
|
spin_unlock(&vfsmount_lock); |
181 |
|
|
} |
182 |
|
|
- return NULL; |
183 |
|
|
+ return q; |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) |
187 |
|
|
@@ -538,11 +570,14 @@ static int do_loopback(struct nameidata |
188 |
|
|
down_write(¤t->namespace->sem); |
189 |
|
|
err = -EINVAL; |
190 |
|
|
if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) { |
191 |
|
|
- err = -ENOMEM; |
192 |
|
|
if (recurse) |
193 |
|
|
mnt = copy_tree(old_nd.mnt, old_nd.dentry); |
194 |
|
|
else |
195 |
|
|
mnt = clone_mnt(old_nd.mnt, old_nd.dentry); |
196 |
|
|
+ if (IS_ERR(mnt)) { |
197 |
|
|
+ err = PTR_ERR(mnt); |
198 |
|
|
+ goto out; |
199 |
|
|
+ } |
200 |
|
|
} |
201 |
|
|
|
202 |
|
|
if (mnt) { |
203 |
|
|
@@ -555,6 +590,7 @@ static int do_loopback(struct nameidata |
204 |
|
|
mntput(mnt); |
205 |
|
|
} |
206 |
|
|
|
207 |
|
|
+ out: |
208 |
|
|
up_write(¤t->namespace->sem); |
209 |
|
|
path_release(&old_nd); |
210 |
|
|
return err; |
211 |
|
|
@@ -654,14 +690,28 @@ static int do_add_mount(struct nameidata |
212 |
|
|
int mnt_flags, char *name, void *data) |
213 |
|
|
{ |
214 |
|
|
struct vfsmount *mnt; |
215 |
|
|
- int err; |
216 |
|
|
+ int err = mount_is_safe(nd); |
217 |
|
|
+ if(err) |
218 |
|
|
+ return err; |
219 |
|
|
|
220 |
|
|
if (!type || !memchr(type, 0, PAGE_SIZE)) |
221 |
|
|
return -EINVAL; |
222 |
|
|
|
223 |
|
|
/* we need capabilities... */ |
224 |
|
|
- if (!capable(CAP_SYS_ADMIN)) |
225 |
|
|
- return -EPERM; |
226 |
|
|
+ if (!capable(CAP_SYS_ADMIN)) { |
227 |
|
|
+ /* but allow "safe" filesystems anyway */ |
228 |
|
|
+ int issafe = 0; |
229 |
|
|
+ struct file_system_type *t = get_fs_type(type); |
230 |
|
|
+ if(t) { |
231 |
|
|
+ issafe = t->fs_flags & FS_SAFE; |
232 |
|
|
+ put_filesystem(t); |
233 |
|
|
+ } |
234 |
|
|
+ if(!issafe) |
235 |
|
|
+ return -EPERM; |
236 |
|
|
+ |
237 |
|
|
+ /* users should not have suid or dev files */ |
238 |
|
|
+ mnt_flags |= (MNT_NOSUID | MNT_NODEV); |
239 |
|
|
+ } |
240 |
|
|
|
241 |
|
|
mnt = do_kern_mount(type, flags, name, data); |
242 |
|
|
err = PTR_ERR(mnt); |
243 |
|
|
@@ -801,6 +851,7 @@ int copy_namespace(int flags, struct tas |
244 |
|
|
struct namespace *new_ns; |
245 |
|
|
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL; |
246 |
|
|
struct fs_struct *fs = tsk->fs; |
247 |
|
|
+ int err; |
248 |
|
|
|
249 |
|
|
if (!namespace) |
250 |
|
|
return 0; |
251 |
|
|
@@ -810,11 +861,7 @@ int copy_namespace(int flags, struct tas |
252 |
|
|
if (!(flags & CLONE_NEWNS)) |
253 |
|
|
return 0; |
254 |
|
|
|
255 |
|
|
- if (!capable(CAP_SYS_ADMIN)) { |
256 |
|
|
- put_namespace(namespace); |
257 |
|
|
- return -EPERM; |
258 |
|
|
- } |
259 |
|
|
- |
260 |
|
|
+ err = -ENOMEM; |
261 |
|
|
new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL); |
262 |
|
|
if (!new_ns) |
263 |
|
|
goto out; |
264 |
|
|
@@ -826,7 +873,8 @@ int copy_namespace(int flags, struct tas |
265 |
|
|
down_write(&tsk->namespace->sem); |
266 |
|
|
/* First pass: copy the tree topology */ |
267 |
|
|
new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root); |
268 |
|
|
- if (!new_ns->root) { |
269 |
|
|
+ if (IS_ERR(new_ns->root)) { |
270 |
|
|
+ err = PTR_ERR(new_ns->root); |
271 |
|
|
up_write(&tsk->namespace->sem); |
272 |
|
|
kfree(new_ns); |
273 |
|
|
goto out; |
274 |
|
|
@@ -876,7 +924,7 @@ int copy_namespace(int flags, struct tas |
275 |
|
|
|
276 |
|
|
out: |
277 |
|
|
put_namespace(namespace); |
278 |
|
|
- return -ENOMEM; |
279 |
|
|
+ return err; |
280 |
|
|
} |
281 |
|
|
|
282 |
|
|
asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name, |
283 |
|
|
diff -rup linux-2.6.5.orig/fs/super.c linux-2.6.5/fs/super.c |
284 |
|
|
--- linux-2.6.5.orig/fs/super.c 2004-04-05 10:50:46.000000000 +0200 |
285 |
|
|
+++ linux-2.6.5/fs/super.c 2004-04-05 11:02:10.000000000 +0200 |
286 |
|
|
@@ -726,7 +726,7 @@ struct vfsmount * |
287 |
|
|
do_kern_mount(const char *fstype, int flags, const char *name, void *data) |
288 |
|
|
{ |
289 |
|
|
struct file_system_type *type = get_fs_type(fstype); |
290 |
|
|
- struct super_block *sb = ERR_PTR(-ENOMEM); |
291 |
|
|
+ struct super_block *sb; |
292 |
|
|
struct vfsmount *mnt; |
293 |
|
|
int error; |
294 |
|
|
char *secdata = NULL; |
295 |
|
|
@@ -735,24 +735,23 @@ do_kern_mount(const char *fstype, int fl |
296 |
|
|
return ERR_PTR(-ENODEV); |
297 |
|
|
|
298 |
|
|
mnt = alloc_vfsmnt(name); |
299 |
|
|
- if (!mnt) |
300 |
|
|
+ error = PTR_ERR(mnt); |
301 |
|
|
+ if (IS_ERR(mnt)) |
302 |
|
|
goto out; |
303 |
|
|
|
304 |
|
|
if (data) { |
305 |
|
|
secdata = alloc_secdata(); |
306 |
|
|
- if (!secdata) { |
307 |
|
|
- sb = ERR_PTR(-ENOMEM); |
308 |
|
|
+ error = -ENOMEM; |
309 |
|
|
+ if (!secdata) |
310 |
|
|
goto out_mnt; |
311 |
|
|
- } |
312 |
|
|
|
313 |
|
|
error = security_sb_copy_data(type, data, secdata); |
314 |
|
|
- if (error) { |
315 |
|
|
- sb = ERR_PTR(error); |
316 |
|
|
+ if (error) |
317 |
|
|
goto out_free_secdata; |
318 |
|
|
- } |
319 |
|
|
} |
320 |
|
|
|
321 |
|
|
sb = type->get_sb(type, flags, name, data); |
322 |
|
|
+ error = PTR_ERR(sb); |
323 |
|
|
if (IS_ERR(sb)) |
324 |
|
|
goto out_free_secdata; |
325 |
|
|
error = security_sb_kern_mount(sb, secdata); |
326 |
|
|
@@ -762,20 +761,20 @@ do_kern_mount(const char *fstype, int fl |
327 |
|
|
mnt->mnt_root = dget(sb->s_root); |
328 |
|
|
mnt->mnt_mountpoint = sb->s_root; |
329 |
|
|
mnt->mnt_parent = mnt; |
330 |
|
|
+ mnt->user = capable(CAP_SYS_ADMIN) ? 0 : current->fsuid; |
331 |
|
|
up_write(&sb->s_umount); |
332 |
|
|
put_filesystem(type); |
333 |
|
|
return mnt; |
334 |
|
|
out_sb: |
335 |
|
|
up_write(&sb->s_umount); |
336 |
|
|
deactivate_super(sb); |
337 |
|
|
- sb = ERR_PTR(error); |
338 |
|
|
out_free_secdata: |
339 |
|
|
free_secdata(secdata); |
340 |
|
|
out_mnt: |
341 |
|
|
free_vfsmnt(mnt); |
342 |
|
|
out: |
343 |
|
|
put_filesystem(type); |
344 |
|
|
- return (struct vfsmount *)sb; |
345 |
|
|
+ return ERR_PTR(error); |
346 |
|
|
} |
347 |
|
|
|
348 |
|
|
struct vfsmount *kern_mount(struct file_system_type *type) |
349 |
|
|
diff -rup linux-2.6.5.orig/include/linux/fs.h linux-2.6.5/include/linux/fs.h |
350 |
|
|
--- linux-2.6.5.orig/include/linux/fs.h 2004-04-05 10:50:50.000000000 +0200 |
351 |
|
|
+++ linux-2.6.5/include/linux/fs.h 2004-04-05 11:03:55.000000000 +0200 |
352 |
|
|
@@ -55,6 +55,12 @@ struct files_stat_struct { |
353 |
|
|
}; |
354 |
|
|
extern struct files_stat_struct files_stat; |
355 |
|
|
|
356 |
|
|
+struct mounts_stat_struct { |
357 |
|
|
+ int nr_mounts; |
358 |
|
|
+ int max_mounts; |
359 |
|
|
+}; |
360 |
|
|
+extern struct mounts_stat_struct mounts_stat; |
361 |
|
|
+ |
362 |
|
|
struct inodes_stat_t { |
363 |
|
|
int nr_inodes; |
364 |
|
|
int nr_unused; |
365 |
|
|
@@ -90,6 +96,7 @@ extern int leases_enable, dir_notify_ena |
366 |
|
|
/* public flags for file_system_type */ |
367 |
|
|
#define FS_REQUIRES_DEV 1 |
368 |
|
|
#define FS_BINARY_MOUNTDATA 2 |
369 |
|
|
+#define FS_SAFE 4 /* Safe to mount by user */ |
370 |
|
|
#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ |
371 |
|
|
#define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon |
372 |
|
|
* as nfs_rename() will be cleaned up |
373 |
|
|
diff -rup linux-2.6.5.orig/include/linux/mount.h linux-2.6.5/include/linux/mount.h |
374 |
|
|
--- linux-2.6.5.orig/include/linux/mount.h 2003-12-18 03:58:08.000000000 +0100 |
375 |
|
|
+++ linux-2.6.5/include/linux/mount.h 2004-04-05 10:54:37.000000000 +0200 |
376 |
|
|
@@ -30,6 +30,7 @@ struct vfsmount |
377 |
|
|
atomic_t mnt_count; |
378 |
|
|
int mnt_flags; |
379 |
|
|
char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ |
380 |
|
|
+ uid_t user; |
381 |
|
|
struct list_head mnt_list; |
382 |
|
|
}; |
383 |
|
|
|
384 |
|
|
diff -rup linux-2.6.5.orig/include/linux/sysctl.h linux-2.6.5/include/linux/sysctl.h |
385 |
|
|
--- linux-2.6.5.orig/include/linux/sysctl.h 2004-04-05 10:50:50.000000000 +0200 |
386 |
|
|
+++ linux-2.6.5/include/linux/sysctl.h 2004-04-05 10:54:37.000000000 +0200 |
387 |
|
|
@@ -624,8 +624,8 @@ enum |
388 |
|
|
FS_NRFILE=6, /* int:current number of allocated filedescriptors */ |
389 |
|
|
FS_MAXFILE=7, /* int:maximum number of filedescriptors that can be allocated */ |
390 |
|
|
FS_DENTRY=8, |
391 |
|
|
- FS_NRSUPER=9, /* int:current number of allocated super_blocks */ |
392 |
|
|
- FS_MAXSUPER=10, /* int:maximum number of super_blocks that can be allocated */ |
393 |
|
|
+ FS_NRMOUNT=9, /* int:current number of mounts */ |
394 |
|
|
+ FS_MAXMOUNT=10, /* int:maximum number of mounts allowed */ |
395 |
|
|
FS_OVERFLOWUID=11, /* int: overflow UID */ |
396 |
|
|
FS_OVERFLOWGID=12, /* int: overflow GID */ |
397 |
|
|
FS_LEASES=13, /* int: leases enabled */ |
398 |
|
|
diff -rup linux-2.6.5.orig/kernel/sysctl.c linux-2.6.5/kernel/sysctl.c |
399 |
|
|
--- linux-2.6.5.orig/kernel/sysctl.c 2004-04-05 10:50:51.000000000 +0200 |
400 |
|
|
+++ linux-2.6.5/kernel/sysctl.c 2004-04-05 10:54:37.000000000 +0200 |
401 |
|
|
@@ -793,6 +793,22 @@ static ctl_table fs_table[] = { |
402 |
|
|
.proc_handler = &proc_dointvec, |
403 |
|
|
}, |
404 |
|
|
{ |
405 |
|
|
+ .ctl_name = FS_NRMOUNT, |
406 |
|
|
+ .procname = "mount-nr", |
407 |
|
|
+ .data = &mounts_stat.nr_mounts, |
408 |
|
|
+ .maxlen = sizeof(int), |
409 |
|
|
+ .mode = 0444, |
410 |
|
|
+ .proc_handler = &proc_dointvec, |
411 |
|
|
+ }, |
412 |
|
|
+ { |
413 |
|
|
+ .ctl_name = FS_MAXMOUNT, |
414 |
|
|
+ .procname = "mount-max", |
415 |
|
|
+ .data = &mounts_stat.max_mounts, |
416 |
|
|
+ .maxlen = sizeof(int), |
417 |
|
|
+ .mode = 0644, |
418 |
|
|
+ .proc_handler = &proc_dointvec, |
419 |
|
|
+ }, |
420 |
|
|
+ { |
421 |
|
|
.ctl_name = FS_OVERFLOWUID, |
422 |
|
|
.procname = "overflowuid", |
423 |
|
|
.data = &fs_overflowuid, |