/[fuse_dbi]/fuse/trunk/patch/user-mount-2.6.5.patch
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /fuse/trunk/patch/user-mount-2.6.5.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Wed Aug 4 11:40:49 2004 UTC (18 years, 4 months ago) by dpavlin
File size: 12424 byte(s)
copy CVS to trunk

1 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(&current->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(&current->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,

  ViewVC Help
Powered by ViewVC 1.1.26