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_base.h>
14 #include <linux/vs_context.h>
15 #include <linux/proc_fs.h>
16 #include <linux/devpts_fs.h>
17 #include <linux/namei.h>
18 #include <linux/mount.h>
19 #include <linux/parser.h>
20 #include <linux/compat.h>
21 #include <linux/vserver/inode.h>
22 #include <linux/vserver/inode_cmd.h>
23 #include <linux/vserver/xid.h>
25 #include <asm/errno.h>
26 #include <asm/uaccess.h>
29 static int __vc_get_iattr(struct inode *in, uint32_t *xid, uint32_t *flags, uint32_t *mask)
31 struct proc_dir_entry *entry;
37 | (IS_BARRIER(in) ? IATTR_BARRIER : 0)
38 | (IS_IUNLINK(in) ? IATTR_IUNLINK : 0)
39 | (IS_IMMUTABLE(in) ? IATTR_IMMUTABLE : 0);
40 *mask = IATTR_IUNLINK | IATTR_IMMUTABLE;
42 if (S_ISDIR(in->i_mode))
43 *mask |= IATTR_BARRIER;
50 switch (in->i_sb->s_magic) {
51 case PROC_SUPER_MAGIC:
52 entry = PROC_I(in)->pde;
54 /* check for specific inodes? */
58 *flags |= (entry->vx_flags & IATTR_FLAGS);
60 *flags |= (PROC_I(in)->vx_flags & IATTR_FLAGS);
63 case DEVPTS_SUPER_MAGIC:
74 int vc_get_iattr(uint32_t id, void __user *data)
77 struct vcmd_ctx_iattr_v1 vc_data = { .xid = -1 };
80 if (!vx_check(0, VX_ADMIN))
82 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
85 ret = user_path_walk_link(vc_data.name, &nd);
87 ret = __vc_get_iattr(nd.dentry->d_inode,
88 &vc_data.xid, &vc_data.flags, &vc_data.mask);
94 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
101 int vc_get_iattr_x32(uint32_t id, void __user *data)
104 struct vcmd_ctx_iattr_v1_x32 vc_data = { .xid = -1 };
107 if (!vx_check(0, VX_ADMIN))
109 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
112 ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
114 ret = __vc_get_iattr(nd.dentry->d_inode,
115 &vc_data.xid, &vc_data.flags, &vc_data.mask);
121 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
126 #endif /* CONFIG_COMPAT */
129 static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uint32_t *mask)
131 struct inode *in = de->d_inode;
132 int error = 0, is_proc = 0, has_xid = 0;
133 struct iattr attr = { 0 };
135 if (!in || !in->i_sb)
138 is_proc = (in->i_sb->s_magic == PROC_SUPER_MAGIC);
139 if ((*mask & IATTR_FLAGS) && !is_proc)
142 has_xid = IS_TAGXID(in) ||
143 (in->i_sb->s_magic == DEVPTS_SUPER_MAGIC);
144 if ((*mask & IATTR_XID) && !has_xid)
147 mutex_lock(&in->i_mutex);
148 if (*mask & IATTR_XID) {
150 attr.ia_valid |= ATTR_XID;
153 if (*mask & IATTR_FLAGS) {
154 struct proc_dir_entry *entry = PROC_I(in)->pde;
155 unsigned int iflags = PROC_I(in)->vx_flags;
157 iflags = (iflags & ~(*mask & IATTR_FLAGS))
158 | (*flags & IATTR_FLAGS);
159 PROC_I(in)->vx_flags = iflags;
161 entry->vx_flags = iflags;
164 if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) {
165 if (*mask & IATTR_IMMUTABLE) {
166 if (*flags & IATTR_IMMUTABLE)
167 in->i_flags |= S_IMMUTABLE;
169 in->i_flags &= ~S_IMMUTABLE;
171 if (*mask & IATTR_IUNLINK) {
172 if (*flags & IATTR_IUNLINK)
173 in->i_flags |= S_IUNLINK;
175 in->i_flags &= ~S_IUNLINK;
177 if (S_ISDIR(in->i_mode) && (*mask & IATTR_BARRIER)) {
178 if (*flags & IATTR_BARRIER)
179 in->i_flags |= S_BARRIER;
181 in->i_flags &= ~S_BARRIER;
183 if (in->i_op && in->i_op->sync_flags) {
184 error = in->i_op->sync_flags(in);
191 if (in->i_op && in->i_op->setattr)
192 error = in->i_op->setattr(de, &attr);
194 error = inode_change_ok(in, &attr);
196 error = inode_setattr(in, &attr);
201 mutex_unlock(&in->i_mutex);
205 int vc_set_iattr(uint32_t id, void __user *data)
208 struct vcmd_ctx_iattr_v1 vc_data;
211 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
213 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
216 ret = user_path_walk_link(vc_data.name, &nd);
218 ret = __vc_set_iattr(nd.dentry,
219 &vc_data.xid, &vc_data.flags, &vc_data.mask);
223 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
230 int vc_set_iattr_x32(uint32_t id, void __user *data)
233 struct vcmd_ctx_iattr_v1_x32 vc_data;
236 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
238 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
241 ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
243 ret = __vc_set_iattr(nd.dentry,
244 &vc_data.xid, &vc_data.flags, &vc_data.mask);
248 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
253 #endif /* CONFIG_COMPAT */
255 /* required by PLK */
256 int vc_iattr_ioctl(struct dentry *de, unsigned int cmd, unsigned long arg)
258 void __user *data = (void __user *)arg;
259 struct vcmd_ctx_iattr_v1 vc_data;
263 * I don't think we need any dget/dput pairs in here as long as
264 * this function is always called from sys_ioctl i.e., de is
265 * a field of a struct file that is guaranteed not to be freed.
267 if (cmd == FIOC_SETIATTR) {
268 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
270 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
272 ret = __vc_set_iattr(de,
273 &vc_data.xid, &vc_data.flags, &vc_data.mask);
276 if (!vx_check(0, VX_ADMIN))
278 ret = __vc_get_iattr(de->d_inode,
279 &vc_data.xid, &vc_data.flags, &vc_data.mask);
282 if (!ret && copy_to_user (data, &vc_data, sizeof(vc_data)))
287 #ifdef CONFIG_VSERVER_LEGACY
289 #define PROC_DYNAMIC_FIRST 0xF0000000UL
291 int vx_proc_ioctl(struct inode * inode, struct file * filp,
292 unsigned int cmd, unsigned long arg)
294 struct proc_dir_entry *entry;
298 if (inode->i_ino < PROC_DYNAMIC_FIRST)
301 entry = PROC_I(inode)->pde;
307 /* fixme: if stealth, return -ENOTTY */
309 flags = entry->vx_flags;
310 if (capable(CAP_CONTEXT))
311 error = put_user(flags, (int __user *) arg);
315 /* fixme: if stealth, return -ENOTTY */
317 if (!capable(CAP_CONTEXT))
320 if (IS_RDONLY(inode))
323 if (get_user(flags, (int __user *) arg))
326 entry->vx_flags = flags;
337 int vx_parse_xid(char *string, xid_t *xid, int remove)
339 static match_table_t tokens = {
343 substring_t args[MAX_OPT_ARGS];
344 int token, option = 0;
349 token = match_token(string, tokens, args);
350 if (token && xid && !match_int(args, &option))
353 vxdprintk(VXD_CBIT(xid, 7),
354 "vx_parse_xid(»%s«): %d:#%d",
355 string, token, option);
357 if (token && remove) {
358 char *p = strstr(string, "xid=");
362 while (*q != '\0' && *q != ',')
373 void vx_propagate_xid(struct nameidata *nd, struct inode *inode)
376 struct vfsmount *mnt;
385 propagate = (mnt->mnt_flags & MNT_XID);
387 new_xid = mnt->mnt_xid;
389 vxdprintk(VXD_CBIT(xid, 7),
390 "vx_propagate_xid(%p[#%lu.%d]): %d,%d",
391 inode, inode->i_ino, inode->i_xid,
392 new_xid, (propagate)?1:0);
395 inode->i_xid = new_xid;
398 #include <linux/module.h>
400 EXPORT_SYMBOL_GPL(vx_propagate_xid);