Blame view

fs/nfsctl.c 2.48 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   *	fs/nfsctl.c
   *
   *	This should eventually move to userland.
   *
   */
715b49ef2   Alan Cox   [PATCH] EDAC: ato...
7
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
  #include <linux/file.h>
  #include <linux/fs.h>
  #include <linux/sunrpc/svc.h>
  #include <linux/nfsd/nfsd.h>
  #include <linux/nfsd/syscall.h>
9789cfe22   Randy Dunlap   nfsctl: add heade...
13
14
  #include <linux/cred.h>
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
20
21
22
23
24
25
26
27
  #include <linux/linkage.h>
  #include <linux/namei.h>
  #include <linux/mount.h>
  #include <linux/syscalls.h>
  #include <asm/uaccess.h>
  
  /*
   * open a file on nfsd fs
   */
  
  static struct file *do_open(char *name, int flags)
  {
  	struct nameidata nd;
16b6287a5   Josef 'Jeff' Sipek   nfsctl: use vfs_p...
28
  	struct vfsmount *mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  	int error;
16b6287a5   Josef 'Jeff' Sipek   nfsctl: use vfs_p...
30
31
32
  	mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
  	if (IS_ERR(mnt))
  		return (struct file *)mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

16b6287a5   Josef 'Jeff' Sipek   nfsctl: use vfs_p...
34
35
  	error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd);
  	mntput(mnt);	/* drop do_kern_mount reference */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
  	if (error)
  		return ERR_PTR(error);
  
  	if (flags == O_RDWR)
3fb64190a   Christoph Hellwig   pass a struct pat...
40
41
  		error = may_open(&nd.path, MAY_READ|MAY_WRITE,
  					   FMODE_READ|FMODE_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  	else
3fb64190a   Christoph Hellwig   pass a struct pat...
43
  		error = may_open(&nd.path, MAY_WRITE, FMODE_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
  
  	if (!error)
745ca2475   David Howells   CRED: Pass creden...
46
47
  		return dentry_open(nd.path.dentry, nd.path.mnt, flags,
  				   current_cred());
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

1d957f9bf   Jan Blunck   Introduce path_put()
49
  	path_put(&nd.path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  	return ERR_PTR(error);
  }
  
  static struct {
  	char *name; int wsize; int rsize;
  } map[] = {
  	[NFSCTL_SVC] = {
  		.name	= ".svc",
  		.wsize	= sizeof(struct nfsctl_svc)
  	},
  	[NFSCTL_ADDCLIENT] = {
  		.name	= ".add",
  		.wsize	= sizeof(struct nfsctl_client)
  	},
  	[NFSCTL_DELCLIENT] = {
  		.name	= ".del",
  		.wsize	= sizeof(struct nfsctl_client)
  	},
  	[NFSCTL_EXPORT] = {
  		.name	= ".export",
  		.wsize	= sizeof(struct nfsctl_export)
  	},
  	[NFSCTL_UNEXPORT] = {
  		.name	= ".unexport",
  		.wsize	= sizeof(struct nfsctl_export)
  	},
  	[NFSCTL_GETFD] = {
  		.name	= ".getfd",
  		.wsize	= sizeof(struct nfsctl_fdparm),
  		.rsize	= NFS_FHSIZE
  	},
  	[NFSCTL_GETFS] = {
  		.name	= ".getfs",
  		.wsize	= sizeof(struct nfsctl_fsparm),
  		.rsize	= sizeof(struct knfsd_fh)
  	},
  };
1e7bfb213   Heiko Carstens   [CVE-2009-0029] S...
87
88
  SYSCALL_DEFINE3(nfsservctl, int, cmd, struct nfsctl_arg __user *, arg,
  		void __user *, res)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
95
96
  {
  	struct file *file;
  	void __user *p = &arg->u;
  	int version;
  	int err;
  
  	if (copy_from_user(&version, &arg->ca_version, sizeof(int)))
  		return -EFAULT;
85c6932ef   Peter Staubach   [PATCH] nfsservct...
97
  	if (version != NFSCTL_VERSION)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

e8c96f8c2   Tobias Klauser   [PATCH] fs: Use A...
100
  	if (cmd < 0 || cmd >= ARRAY_SIZE(map) || !map[cmd].name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
105
106
107
108
109
110
111
112
113
  		return -EINVAL;
  
  	file = do_open(map[cmd].name, map[cmd].rsize ? O_RDWR : O_WRONLY);	
  	if (IS_ERR(file))
  		return PTR_ERR(file);
  	err = file->f_op->write(file, p, map[cmd].wsize, &file->f_pos);
  	if (err >= 0 && map[cmd].rsize)
  		err = file->f_op->read(file, res, map[cmd].rsize, &file->f_pos);
  	if (err >= 0)
  		err = 0;
  	fput(file);
  	return err;
  }