Setting tag linux-2.6-22-50
[linux-2.6.git] / linux-2.6-700-fperm.patch
1 diff -Nurp linux-2.6.22-690/fs/attr.c linux-2.6.22-700/fs/attr.c
2 --- linux-2.6.22-690/fs/attr.c  2009-01-08 18:12:22.000000000 +0100
3 +++ linux-2.6.22-700/fs/attr.c  2009-01-08 18:59:11.000000000 +0100
4 @@ -17,6 +17,7 @@
5  #include <linux/proc_fs.h>
6  #include <linux/devpts_fs.h>
7  #include <linux/vs_base.h>
8 +#include <linux/vs_tag.h>
9  
10  /* Taken over from the old code... */
11  
12 @@ -59,26 +60,9 @@ int inode_change_ok(struct inode *inode,
13                         goto error;
14         }
15  
16 -       /* Check for evil vserver activity */
17 -       if (vx_check(0, VS_ADMIN))
18 -               goto fine;
19 -
20 -       if (IS_BARRIER(inode)) {
21 -               vxwprintk_task(1, "messing with the barrier.");
22 +       if (dx_permission(inode, MAY_WRITE))
23                 goto error;
24 -       }
25 -       switch (inode->i_sb->s_magic) {
26 -               case PROC_SUPER_MAGIC:
27 -                       /* maybe allow that in the future? */
28 -                       vxwprintk_task(1, "messing with the procfs.");
29 -                       goto error;
30 -               case DEVPTS_SUPER_MAGIC:
31 -                       /* devpts is xid tagged */
32 -                       if (vx_check((xid_t)inode->i_tag, VS_IDENT))
33 -                               goto fine;
34 -                       vxwprintk_task(1, "messing with the devpts.");
35 -                       goto error;
36 -       }
37 +
38  fine:
39         retval = 0;
40  error:
41 diff -Nurp linux-2.6.22-690/fs/namei.c linux-2.6.22-700/fs/namei.c
42 --- linux-2.6.22-690/fs/namei.c 2009-01-08 18:12:22.000000000 +0100
43 +++ linux-2.6.22-700/fs/namei.c 2009-01-08 18:33:41.000000000 +0100
44 @@ -233,26 +233,74 @@ int generic_permission(struct inode *ino
45  
46  static inline int dx_barrier(struct inode *inode)
47  {
48 -       if (IS_BARRIER(inode) && !vx_check(0, VS_ADMIN)) {
49 +       if (IS_BARRIER(inode) && !vx_check(0, VS_ADMIN | VS_WATCH)) {
50                 vxwprintk_task(1, "did hit the barrier.");
51                 return 1;
52         }
53         return 0;
54  }
55  
56 -static inline int dx_permission(struct inode *inode, int mask, struct nameidata *nd)
57 +static inline int __dx_permission(struct inode *inode, int mask)
58  {
59         if (dx_barrier(inode))
60                 return -EACCES;
61 -       if (dx_notagcheck(nd) ||
62 -           dx_check(inode->i_tag, DX_HOSTID|DX_ADMIN|DX_WATCH|DX_IDENT))
63 -               return 0;
64  
65 -       vxwprintk_task(1, "denied access to %p[#%d,%lu] »%s«.",
66 -               inode, inode->i_tag, inode->i_ino, vxd_cond_path(nd));
67 +       if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) {
68 +               /* devpts is xid tagged */
69 +               if (S_ISDIR(inode->i_mode) ||
70 +                   vx_check((xid_t)inode->i_tag, VS_IDENT | VS_WATCH_P))
71 +                       return 0;
72 +       }
73 +       else if (inode->i_sb->s_magic == PROC_SUPER_MAGIC) {
74 +               struct proc_dir_entry *de = PDE(inode);
75 +
76 +               if (de && !vx_hide_check(0, de->vx_flags))
77 +                       goto out;
78 +
79 +               if ((mask & (MAY_WRITE | MAY_APPEND))) {
80 +                       struct pid *pid;
81 +                       struct task_struct *tsk;
82 +
83 +                       if (vx_check(0, VS_ADMIN | VS_WATCH_P) ||
84 +                           vx_flags(VXF_STATE_SETUP, 0) ||
85 +                           vx_capable(CAP_SYS_ADMIN, VXC_PROC_WRITE))
86 +                               return 0;
87 +
88 +                       pid = PROC_I(inode)->pid;
89 +                       if (!pid)
90 +                               goto out;
91 +
92 +                       tsk = pid_task(pid, PIDTYPE_PID);
93 +                       vxdprintk(VXD_CBIT(tag, 0), "accessing %p[#%u]",
94 +                               tsk, (tsk ? vx_task_xid(tsk) : 0));
95 +                       if (tsk && vx_check(vx_task_xid(tsk), VS_IDENT | VS_WATCH_P))
96 +                               return 0;
97 +               }
98 +               else
99 +                       return 0;
100 +       }
101 +       else {
102 +               if (dx_notagcheck(inode->i_sb) ||
103 +                   dx_check(inode->i_tag, DX_HOSTID | DX_ADMIN | DX_WATCH |
104 +                            DX_IDENT))
105 +                       return 0;
106 +       }
107 +
108 +out:
109         return -EACCES;
110  }
111  
112 +int dx_permission(struct inode *inode, int mask)
113 +{
114 +       int ret = __dx_permission(inode, mask);
115 +       if (unlikely(ret)) {
116 +               vxwprintk_task(1, "denied %x access to %s:%p[#%d,%lu]",
117 +                       mask, inode->i_sb->s_id, inode, inode->i_tag,
118 +                       inode->i_ino);
119 +       }
120 +       return ret;
121 +}
122 +
123  int permission(struct inode *inode, int mask, struct nameidata *nd)
124  {
125         umode_t mode = inode->i_mode;
126 @@ -284,14 +332,13 @@ int permission(struct inode *inode, int 
127                         (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
128                 return -EACCES;
129  
130 +       retval = dx_permission(inode, mask);
131 +       if (retval)
132 +               return retval;
133 +
134         /* Ordinary permission routines do not understand MAY_APPEND. */
135         submask = mask & ~MAY_APPEND;
136  
137 -       if ((inode->i_sb->s_magic != DEVPTS_SUPER_MAGIC) &&
138 -               (inode->i_sb->s_magic != PROC_SUPER_MAGIC) &&
139 -               (retval = dx_permission(inode, mask, nd)))
140 -               return retval;
141 -
142         if (inode->i_op && inode->i_op->permission)
143                 retval = inode->i_op->permission(inode, submask, nd);
144         else
145 @@ -817,27 +864,18 @@ static int do_lookup(struct nameidata *n
146         if (!inode)
147                 goto done;
148  
149 -       if (inode->i_sb->s_magic == PROC_SUPER_MAGIC) {
150 -               struct proc_dir_entry *de = PDE(inode);
151 +       if (__dx_permission(inode, MAY_ACCESS))
152 +               goto hidden;
153  
154 -               if (de && !vx_hide_check(0, de->vx_flags))
155 -                       goto hidden;
156 -       } else if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) {
157 -               if (!vx_check((xid_t)inode->i_tag, VS_WATCH_P | VS_IDENT))
158 -                       goto hidden;
159 -       } else {
160 -               if (!dx_notagcheck(nd) && !dx_check(inode->i_tag,
161 -                       DX_WATCH | DX_ADMIN | DX_HOSTID | DX_IDENT))
162 -                       goto hidden;
163 -       }
164  done:
165         path->mnt = mnt;
166         path->dentry = dentry;
167         __follow_mount(path);
168         return 0;
169  hidden:
170 -       vxwprintk_task(1, "did lookup hidden %p[#%d,%lu] »%s«.",
171 -               inode, inode->i_tag, inode->i_ino, vxd_path(dentry, mnt));
172 +       vxwprintk_task(1, "did lookup hidden %s:%p[#%d,%lu] »%s«.",
173 +               inode->i_sb->s_id, inode, inode->i_tag, inode->i_ino,
174 +               vxd_path(dentry, mnt));
175         dput(dentry);
176         return -ENOENT;
177  
178 diff -Nurp linux-2.6.22-690/fs/namespace.c linux-2.6.22-700/fs/namespace.c
179 --- linux-2.6.22-690/fs/namespace.c     2009-01-08 18:12:22.000000000 +0100
180 +++ linux-2.6.22-700/fs/namespace.c     2009-01-08 18:59:35.000000000 +0100
181 @@ -1470,9 +1470,7 @@ long do_mount(char *dev_name, char *dir_
182         if (data_page)
183                 ((char *)data_page)[PAGE_SIZE - 1] = 0;
184  
185 -       retval = dx_parse_tag(data_page, &tag, 1);
186 -       if (retval) {
187 -               mnt_flags |= retval;
188 +       if (dx_parse_tag(data_page, &tag, 1, &mnt_flags, &flags)) {
189                 /* FIXME: bind and re-mounts get the tag flag? */
190                 if (flags & (MS_BIND|MS_REMOUNT))
191                         flags |= MS_TAGID;
192 diff -Nurp linux-2.6.22-690/include/linux/fs.h linux-2.6.22-700/include/linux/fs.h
193 --- linux-2.6.22-690/include/linux/fs.h 2009-01-08 18:12:34.000000000 +0100
194 +++ linux-2.6.22-700/include/linux/fs.h 2009-01-08 18:42:32.000000000 +0100
195 @@ -60,6 +60,7 @@ extern int dir_notify_enable;
196  #define MAY_WRITE 2
197  #define MAY_READ 4
198  #define MAY_APPEND 8
199 +#define MAY_ACCESS 16
200  
201  #define FMODE_READ 1
202  #define FMODE_WRITE 2
203 @@ -125,6 +126,7 @@ extern int dir_notify_enable;
204  #define MS_RELATIME    (1<<21) /* Update atime relative to mtime/ctime. */
205  #define MS_TAGGED      (1<<24) /* use generic inode tagging */
206  #define MS_TAGID       (1<<25) /* use specific tag for this mount */
207 +#define MS_NOTAGCHECK  (1<<26) /* don't check tags */
208  #define MS_ACTIVE      (1<<30)
209  #define MS_NOUSER      (1<<31)
210  
211 diff -Nurp linux-2.6.22-690/include/linux/mount.h linux-2.6.22-700/include/linux/mount.h
212 --- linux-2.6.22-690/include/linux/mount.h      2009-01-08 18:12:23.000000000 +0100
213 +++ linux-2.6.22-700/include/linux/mount.h      2009-01-08 18:41:37.000000000 +0100
214 @@ -40,7 +40,6 @@ struct mnt_namespace;
215  
216  #define MNT_TAGID      0x10000
217  #define MNT_NOTAG      0x20000
218 -#define MNT_NOTAGCHECK 0x40000
219  
220  struct vfsmount {
221         struct list_head mnt_hash;
222 diff -Nurp linux-2.6.22-690/include/linux/vserver/context.h linux-2.6.22-700/include/linux/vserver/context.h
223 --- linux-2.6.22-690/include/linux/vserver/context.h    2009-01-08 18:12:24.000000000 +0100
224 +++ linux-2.6.22-700/include/linux/vserver/context.h    2009-01-08 18:49:20.000000000 +0100
225 @@ -73,6 +73,8 @@
226  
227  #define VXC_KTHREAD            0x01000000
228  
229 +#define VXC_PROC_WRITE         0x80000000ULL
230 +
231  
232  #ifdef __KERNEL__
233  
234 diff -Nurp linux-2.6.22-690/include/linux/vserver/tag.h linux-2.6.22-700/include/linux/vserver/tag.h
235 --- linux-2.6.22-690/include/linux/vserver/tag.h        2009-01-08 18:12:24.000000000 +0100
236 +++ linux-2.6.22-700/include/linux/vserver/tag.h        2009-01-08 18:41:14.000000000 +0100
237 @@ -125,10 +125,11 @@ struct peer_tag {
238         int32_t nid;
239  };
240  
241 -#define dx_notagcheck(nd) \
242 -       ((nd) && (nd)->mnt && ((nd)->mnt->mnt_flags & MNT_NOTAGCHECK))
243 +#define dx_notagcheck(sb) \
244 +       ((sb) && ((sb)->s_flags & MS_NOTAGCHECK))
245  
246 -int dx_parse_tag(char *string, tag_t *tag, int remove);
247 +int dx_parse_tag(char *string, tag_t *tag, int remove, int *mnt_flags,
248 +                unsigned long *flags);
249  
250  #ifdef CONFIG_PROPAGATE
251  
252 diff -Nurp linux-2.6.22-690/include/linux/vs_tag.h linux-2.6.22-700/include/linux/vs_tag.h
253 --- linux-2.6.22-690/include/linux/vs_tag.h     2009-01-08 18:12:24.000000000 +0100
254 +++ linux-2.6.22-700/include/linux/vs_tag.h     2009-01-08 18:37:43.000000000 +0100
255 @@ -38,6 +38,9 @@ static inline int __dx_check(tag_t cid, 
256                 ((mode & DX_HOSTID) && (id == 0)));
257  }
258  
259 +struct inode;
260 +int dx_permission(struct inode *inode, int mask);
261 +
262  #else
263  #warning duplicate inclusion
264  #endif
265 diff -Nurp linux-2.6.22-690/kernel/vserver/inode.c linux-2.6.22-700/kernel/vserver/inode.c
266 --- linux-2.6.22-690/kernel/vserver/inode.c     2009-01-08 18:12:31.000000000 +0100
267 +++ linux-2.6.22-700/kernel/vserver/inode.c     2009-01-08 19:16:55.000000000 +0100
268 @@ -325,56 +325,69 @@ static void __dx_parse_remove(char *stri
269         }
270  }
271  
272 -static inline
273 -int __dx_parse_tag(char *string, tag_t *tag, int remove)
274 +int dx_parse_tag(char *string, tag_t *tag, int remove, int *mnt_flags,
275 +                unsigned long *flags)
276  {
277 +       int set = 0;
278         substring_t args[MAX_OPT_ARGS];
279         int token, option = 0;
280 +       char *s, *p, *opts;
281  
282         if (!string)
283                 return 0;
284 +       s = kstrdup(string, GFP_KERNEL | GFP_ATOMIC);
285 +       if (!s)
286 +               return 0;
287  
288 -       token = match_token(string, tokens, args);
289 -
290 -       vxdprintk(VXD_CBIT(tag, 7),
291 -               "dx_parse_tag(»%s«): %d:#%d",
292 -               string, token, option);
293 -
294 -       switch (token) {
295 -       case Opt_tag:
296 -               if (tag)
297 -                       *tag = 0;
298 -               if (remove)
299 -                       __dx_parse_remove(string, "tag");
300 -               return MNT_TAGID;
301 -       case Opt_notag:
302 -               if (remove)
303 -                       __dx_parse_remove(string, "notag");
304 -               return MNT_NOTAG;
305 -       case Opt_notagcheck:
306 -               if (remove)
307 -                       __dx_parse_remove(string, "notagcheck");
308 -               return MNT_NOTAGCHECK;
309 -       case Opt_tagid:
310 -               if (tag && !match_int(args, &option))
311 -                       *tag = option;
312 -               if (remove)
313 -                       __dx_parse_remove(string, "tagid");
314 -               return MNT_TAGID;
315 -       }
316 -       return 0;
317 -}
318 -
319 -int dx_parse_tag(char *string, tag_t *tag, int remove)
320 -{
321 -       int retval, flags = 0;
322  #ifdef CONFIG_VSERVER_FILESHARING
323 -       flags |= MNT_NOTAGCHECK;
324 +       *flags |= MS_NOTAGCHECK;
325  #endif
326  
327 -       while ((retval = __dx_parse_tag(string, tag, remove)))
328 -               flags |= retval;
329 -       return flags;
330 +       opts = s;
331 +       while ((p = strsep(&opts, ",")) != NULL) {
332 +               token = match_token(p, tokens, args);
333 +
334 +               vxdprintk(VXD_CBIT(tag, 7),
335 +                       "dx_parse_tag(»%s«): %d:#%d",
336 +                       p, token, option);
337 +
338 +               switch (token) {
339 +#ifdef CONFIG_PROPAGATE
340 +               case Opt_tag:
341 +                       if (tag)
342 +                               *tag = 0;
343 +                       if (remove)
344 +                               __dx_parse_remove(s, "tag");
345 +                       *mnt_flags |= MNT_TAGID;
346 +                       set |= MNT_TAGID;
347 +                       break;
348 +               case Opt_notag:
349 +                       if (remove)
350 +                               __dx_parse_remove(s, "notag");
351 +                       *mnt_flags |= MNT_NOTAG;
352 +                       set |= MNT_NOTAG;
353 +                       break;
354 +               case Opt_tagid:
355 +                       if (tag && !match_int(args, &option))
356 +                               *tag = option;
357 +                       if (remove)
358 +                               __dx_parse_remove(s, "tagid");
359 +                       *mnt_flags |= MNT_TAGID;
360 +                       set |= MNT_TAGID;
361 +                       break;
362 +#endif
363 +               case Opt_notagcheck:
364 +                       if (remove)
365 +                               __dx_parse_remove(s, "notagcheck");
366 +                       *flags |= MS_NOTAGCHECK;
367 +                       set |= MS_NOTAGCHECK;
368 +                       break;
369 +               }
370 +       }
371 +       if (set)
372 +               strcpy(string, s);
373 +       kfree(s);
374 +       return set;
375  }
376  
377  #ifdef CONFIG_PROPAGATE