2 * linux/kernel/vserver/inode.c
4 * Virtual Server: File System Support
6 * Copyright (C) 2004-2007 Herbert Pötzl
8 * V0.01 separated from vcontext V0.05
12 #include <linux/sched.h>
13 #include <linux/proc_fs.h>
14 #include <linux/devpts_fs.h>
15 #include <linux/namei.h>
16 #include <linux/mount.h>
17 #include <linux/parser.h>
18 #include <linux/compat.h>
19 #include <linux/vserver/inode.h>
20 #include <linux/vserver/inode_cmd.h>
21 #include <linux/vs_base.h>
22 #include <linux/vs_tag.h>
24 #include <asm/errno.h>
25 #include <asm/uaccess.h>
28 static int __vc_get_iattr(struct inode *in, uint32_t *tag, 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;
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 (copy_from_user (&vc_data, data, sizeof(vc_data)))
82 ret = user_path_walk_link(vc_data.name, &nd);
84 ret = __vc_get_iattr(nd.dentry->d_inode,
85 &vc_data.xid, &vc_data.flags, &vc_data.mask);
91 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
98 int vc_get_iattr_x32(uint32_t id, void __user *data)
101 struct vcmd_ctx_iattr_v1_x32 vc_data = { .xid = -1 };
104 if (!vx_check(0, VS_ADMIN))
106 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
109 ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
111 ret = __vc_get_iattr(nd.dentry->d_inode,
112 &vc_data.xid, &vc_data.flags, &vc_data.mask);
118 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
123 #endif /* CONFIG_COMPAT */
126 static int __vc_set_iattr(struct dentry *de, uint32_t *tag, uint32_t *flags, uint32_t *mask)
128 struct inode *in = de->d_inode;
129 int error = 0, is_proc = 0, has_tag = 0;
130 struct iattr attr = { 0 };
132 if (!in || !in->i_sb)
135 is_proc = (in->i_sb->s_magic == PROC_SUPER_MAGIC);
136 if ((*mask & IATTR_FLAGS) && !is_proc)
139 has_tag = IS_TAGGED(in) ||
140 (in->i_sb->s_magic == DEVPTS_SUPER_MAGIC);
141 if ((*mask & IATTR_TAG) && !has_tag)
144 mutex_lock(&in->i_mutex);
145 if (*mask & IATTR_TAG) {
147 attr.ia_valid |= ATTR_TAG;
150 if (*mask & IATTR_FLAGS) {
151 struct proc_dir_entry *entry = PROC_I(in)->pde;
152 unsigned int iflags = PROC_I(in)->vx_flags;
154 iflags = (iflags & ~(*mask & IATTR_FLAGS))
155 | (*flags & IATTR_FLAGS);
156 PROC_I(in)->vx_flags = iflags;
158 entry->vx_flags = iflags;
161 if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) {
162 if (*mask & IATTR_IMMUTABLE) {
163 if (*flags & IATTR_IMMUTABLE)
164 in->i_flags |= S_IMMUTABLE;
166 in->i_flags &= ~S_IMMUTABLE;
168 if (*mask & IATTR_IUNLINK) {
169 if (*flags & IATTR_IUNLINK)
170 in->i_flags |= S_IUNLINK;
172 in->i_flags &= ~S_IUNLINK;
174 if (S_ISDIR(in->i_mode) && (*mask & IATTR_BARRIER)) {
175 if (*flags & IATTR_BARRIER)
176 in->i_flags |= S_BARRIER;
178 in->i_flags &= ~S_BARRIER;
180 if (in->i_op && in->i_op->sync_flags) {
181 error = in->i_op->sync_flags(in);
188 if (in->i_op && in->i_op->setattr)
189 error = in->i_op->setattr(de, &attr);
191 error = inode_change_ok(in, &attr);
193 error = inode_setattr(in, &attr);
198 mutex_unlock(&in->i_mutex);
202 int vc_set_iattr(uint32_t id, void __user *data)
205 struct vcmd_ctx_iattr_v1 vc_data;
208 if (!capable(CAP_LINUX_IMMUTABLE))
210 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
213 ret = user_path_walk_link(vc_data.name, &nd);
215 ret = __vc_set_iattr(nd.dentry,
216 &vc_data.xid, &vc_data.flags, &vc_data.mask);
220 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
227 int vc_set_iattr_x32(uint32_t id, void __user *data)
230 struct vcmd_ctx_iattr_v1_x32 vc_data;
233 if (!capable(CAP_LINUX_IMMUTABLE))
235 if (copy_from_user (&vc_data, data, sizeof(vc_data)))
238 ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
240 ret = __vc_set_iattr(nd.dentry,
241 &vc_data.xid, &vc_data.flags, &vc_data.mask);
245 if (copy_to_user (data, &vc_data, sizeof(vc_data)))
250 #endif /* CONFIG_COMPAT */
252 #ifdef CONFIG_VSERVER_LEGACY
254 #define PROC_DYNAMIC_FIRST 0xF0000000UL
256 int vx_proc_ioctl(struct inode * inode, struct file * filp,
257 unsigned int cmd, unsigned long arg)
259 struct proc_dir_entry *entry;
263 if (inode->i_ino < PROC_DYNAMIC_FIRST)
266 entry = PROC_I(inode)->pde;
272 /* fixme: if stealth, return -ENOTTY */
274 flags = entry->vx_flags;
275 if (capable(CAP_CONTEXT))
276 error = put_user(flags, (int __user *) arg);
280 /* fixme: if stealth, return -ENOTTY */
282 if (!capable(CAP_CONTEXT))
285 if (IS_RDONLY(inode))
288 if (get_user(flags, (int __user *) arg))
291 entry->vx_flags = flags;
299 #endif /* CONFIG_VSERVER_LEGACY */
301 #ifdef CONFIG_PROPAGATE
303 int dx_parse_tag(char *string, tag_t *tag, int remove)
305 static match_table_t tokens = {
309 substring_t args[MAX_OPT_ARGS];
310 int token, option = 0;
315 token = match_token(string, tokens, args);
316 if (token && tag && !match_int(args, &option))
319 vxdprintk(VXD_CBIT(tag, 7),
320 "dx_parse_tag(»%s«): %d:#%d",
321 string, token, option);
323 if ((token == 1) && remove) {
324 char *p = strstr(string, "tagid=");
328 while (*q != '\0' && *q != ',')
339 void __dx_propagate_tag(struct nameidata *nd, struct inode *inode)
342 struct vfsmount *mnt;
351 propagate = (mnt->mnt_flags & MNT_TAGID);
353 new_tag = mnt->mnt_tag;
355 vxdprintk(VXD_CBIT(tag, 7),
356 "dx_propagate_tag(%p[#%lu.%d]): %d,%d",
357 inode, inode->i_ino, inode->i_tag,
358 new_tag, (propagate)?1:0);
361 inode->i_tag = new_tag;
364 #include <linux/module.h>
366 EXPORT_SYMBOL_GPL(__dx_propagate_tag);
368 #endif /* CONFIG_PROPAGATE */