2 * linux/kernel/vserver/inode.c
4 * Virtual Server: File System Support
6 * Copyright (C) 2004-2005 Herbert Pötzl
8 * V0.01 separated from vcontext V0.05
12 #include <linux/sched.h>
13 #include <linux/vs_context.h>
14 #include <linux/proc_fs.h>
15 #include <linux/devpts_fs.h>
16 #include <linux/namei.h>
17 #include <linux/mount.h>
18 #include <linux/parser.h>
19 #include <linux/compat.h>
20 #include <linux/vserver/inode.h>
21 #include <linux/vserver/inode_cmd.h>
22 #include <linux/vserver/xid.h>
24 #include <asm/errno.h>
25 #include <asm/uaccess.h>
28 static int __vc_get_iattr(struct inode *in, uint32_t *xid, uint32_t *flags, uint32_t *mask)
30 struct proc_dir_entry *entry;
36 | (IS_BARRIER(in) ? IATTR_BARRIER : 0)
37 | (IS_IUNLINK(in) ? IATTR_IUNLINK : 0)
38 | (IS_IMMUTABLE(in) ? IATTR_IMMUTABLE : 0);
39 *mask = IATTR_IUNLINK | IATTR_IMMUTABLE;
41 if (S_ISDIR(in->i_mode))
42 *mask |= IATTR_BARRIER;
44 if (in->i_sb->s_flags & MS_TAGXID) {
49 switch (in->i_sb->s_magic) {
50 case PROC_SUPER_MAGIC:
51 entry = PROC_I(in)->pde;
53 /* check for specific inodes? */
57 *flags |= (entry->vx_flags & IATTR_FLAGS);
59 *flags |= (PROC_I(in)->vx_flags & IATTR_FLAGS);
62 case DEVPTS_SUPER_MAGIC:
73 int vc_get_iattr(uint32_t id, void __user *data)
76 struct vcmd_ctx_iattr_v1 vc_data = { .xid = -1 };
79 if (!vx_check(0, VX_ADMIN))
81 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
84 ret = user_path_walk_link(vc_data.name, &nd);
86 ret = __vc_get_iattr(nd.dentry->d_inode,
87 &vc_data.xid, &vc_data.flags, &vc_data.mask);
93 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
100 int vc_get_iattr_x32(uint32_t id, void __user *data)
103 struct vcmd_ctx_iattr_v1_x32 vc_data = { .xid = -1 };
106 if (!vx_check(0, VX_ADMIN))
108 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
111 ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
113 ret = __vc_get_iattr(nd.dentry->d_inode,
114 &vc_data.xid, &vc_data.flags, &vc_data.mask);
120 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
125 #endif /* CONFIG_COMPAT */
128 static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uint32_t *mask)
130 struct inode *in = de->d_inode;
131 int error = 0, is_proc = 0, has_xid = 0;
133 if (!in || !in->i_sb)
136 is_proc = (in->i_sb->s_magic == PROC_SUPER_MAGIC);
137 if ((*mask & IATTR_FLAGS) && !is_proc)
140 has_xid = (in->i_sb->s_flags & MS_TAGXID) ||
141 (in->i_sb->s_magic == DEVPTS_SUPER_MAGIC);
142 if ((*mask & IATTR_XID) && !has_xid)
146 if (*mask & IATTR_XID)
149 if (*mask & IATTR_FLAGS) {
150 struct proc_dir_entry *entry = PROC_I(in)->pde;
151 unsigned int iflags = PROC_I(in)->vx_flags;
153 iflags = (iflags & ~(*mask & IATTR_FLAGS))
154 | (*flags & IATTR_FLAGS);
155 PROC_I(in)->vx_flags = iflags;
157 entry->vx_flags = iflags;
160 if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) {
163 attr.ia_valid = ATTR_ATTR_FLAG;
165 (IS_IMMUTABLE(in) ? ATTR_FLAG_IMMUTABLE : 0) |
166 (IS_IUNLINK(in) ? ATTR_FLAG_IUNLINK : 0) |
167 (IS_BARRIER(in) ? ATTR_FLAG_BARRIER : 0);
169 if (*mask & IATTR_IMMUTABLE) {
170 if (*flags & IATTR_IMMUTABLE)
171 attr.ia_attr_flags |= ATTR_FLAG_IMMUTABLE;
173 attr.ia_attr_flags &= ~ATTR_FLAG_IMMUTABLE;
175 if (*mask & IATTR_IUNLINK) {
176 if (*flags & IATTR_IUNLINK)
177 attr.ia_attr_flags |= ATTR_FLAG_IUNLINK;
179 attr.ia_attr_flags &= ~ATTR_FLAG_IUNLINK;
181 if (S_ISDIR(in->i_mode) && (*mask & IATTR_BARRIER)) {
182 if (*flags & IATTR_BARRIER)
183 attr.ia_attr_flags |= ATTR_FLAG_BARRIER;
185 attr.ia_attr_flags &= ~ATTR_FLAG_BARRIER;
187 if (in->i_op && in->i_op->setattr)
188 error = in->i_op->setattr(de, &attr);
190 error = inode_change_ok(in, &attr);
192 error = inode_setattr(in, &attr);
196 mark_inode_dirty(in);
201 int vc_set_iattr(uint32_t id, void __user *data)
204 struct vcmd_ctx_iattr_v1 vc_data;
207 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
209 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
212 ret = user_path_walk_link(vc_data.name, &nd);
214 ret = __vc_set_iattr(nd.dentry,
215 &vc_data.xid, &vc_data.flags, &vc_data.mask);
219 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
226 int vc_set_iattr_x32(uint32_t id, void __user *data)
229 struct vcmd_ctx_iattr_v1_x32 vc_data;
232 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
234 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
237 ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
239 ret = __vc_set_iattr(nd.dentry,
240 &vc_data.xid, &vc_data.flags, &vc_data.mask);
244 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
249 #endif /* CONFIG_COMPAT */
251 #ifdef CONFIG_VSERVER_LEGACY
253 #define PROC_DYNAMIC_FIRST 0xF0000000UL
255 int vx_proc_ioctl(struct inode * inode, struct file * filp,
256 unsigned int cmd, unsigned long arg)
258 struct proc_dir_entry *entry;
262 if (inode->i_ino < PROC_DYNAMIC_FIRST)
265 entry = PROC_I(inode)->pde;
271 /* fixme: if stealth, return -ENOTTY */
273 flags = entry->vx_flags;
274 if (capable(CAP_CONTEXT))
275 error = put_user(flags, (int *) arg);
279 /* fixme: if stealth, return -ENOTTY */
281 if (!capable(CAP_CONTEXT))
284 if (IS_RDONLY(inode))
287 if (get_user(flags, (int *) arg))
290 entry->vx_flags = flags;
301 int vx_parse_xid(char *string, xid_t *xid, int remove)
303 static match_table_t tokens = {
307 substring_t args[MAX_OPT_ARGS];
308 int token, option = 0;
313 token = match_token(string, tokens, args);
314 if (token && xid && !match_int(args, &option))
317 vxdprintk(VXD_CBIT(xid, 7),
318 "vx_parse_xid(»%s«): %d:#%d",
319 string, token, option);
321 if (token && remove) {
322 char *p = strstr(string, "xid=");
326 while (*q != '\0' && *q != ',')
337 void vx_propagate_xid(struct nameidata *nd, struct inode *inode)
340 struct vfsmount *mnt;
349 propagate = (mnt->mnt_flags & MNT_XID);
351 new_xid = mnt->mnt_xid;
353 vxdprintk(VXD_CBIT(xid, 7),
354 "vx_propagate_xid(%p[#%lu.%d]): %d,%d",
355 inode, inode->i_ino, inode->i_xid,
356 new_xid, (propagate)?1:0);
359 inode->i_xid = new_xid;
362 #include <linux/module.h>
364 EXPORT_SYMBOL_GPL(vx_propagate_xid);